Merge pull request #4862 from element-hq/feature/fga/room-version-upgrade

Feature : room version upgrade
This commit is contained in:
ganfra 2025-06-16 21:17:59 +02:00 committed by GitHub
commit 2bdb3f8a1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
85 changed files with 494 additions and 138 deletions

View file

@ -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)
} }

View file

@ -49,18 +49,21 @@ 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
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.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.alias.matches import io.element.android.libraries.matrix.api.room.alias.matches
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.mediaplayer.api.MediaPlayer import io.element.android.libraries.mediaplayer.api.MediaPlayer
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -70,6 +73,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,
@ -157,7 +161,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) {
@ -173,7 +177,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,
) { ) {
@ -183,7 +186,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!") displaySameRoomToast()
} }
} else { } else {
callbacks.forEach { it.onPermalinkClick(roomLink) } callbacks.forEach { it.onPermalinkClick(roomLink) }
@ -210,6 +213,15 @@ class MessagesNode @AssistedInject constructor(
callbacks.forEach { it.onPreviewAttachments(attachments) } callbacks.forEach { it.onPreviewAttachments(attachments) }
} }
override fun onNavigateToRoom(roomId: RoomId) {
if (roomId == room.roomId) {
displaySameRoomToast()
} 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() }
} }
@ -230,6 +242,10 @@ class MessagesNode @AssistedInject constructor(
callbacks.forEach { it.onViewKnockRequests() } callbacks.forEach { it.onViewKnockRequests() }
} }
private fun displaySameRoomToast() {
context.toast(CommonStrings.screen_room_permalink_same_room_android)
}
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val activity = requireNotNull(LocalActivity.current) val activity = requireNotNull(LocalActivity.current)
@ -255,13 +271,13 @@ class MessagesNode @AssistedInject constructor(
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,

View file

@ -270,6 +270,7 @@ class MessagesPresenter @AssistedInject constructor(
pinnedMessagesBannerState = pinnedMessagesBannerState, pinnedMessagesBannerState = pinnedMessagesBannerState,
dmUserVerificationState = dmUserVerificationState, dmUserVerificationState = dmUserVerificationState,
roomMemberModerationState = roomMemberModerationState, roomMemberModerationState = roomMemberModerationState,
successorRoom = roomInfo.successorRoom,
eventSink = { handleEvents(it) } eventSink = { handleEvents(it) }
) )
} }

View file

@ -26,6 +26,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
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.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@Immutable @Immutable
@ -56,5 +57,6 @@ data class MessagesState(
val pinnedMessagesBannerState: PinnedMessagesBannerState, val pinnedMessagesBannerState: PinnedMessagesBannerState,
val dmUserVerificationState: IdentityState?, val dmUserVerificationState: IdentityState?,
val roomMemberModerationState: RoomMemberModerationState, val roomMemberModerationState: RoomMemberModerationState,
val successorRoom: SuccessorRoom?,
val eventSink: (MessagesEvents) -> Unit val eventSink: (MessagesEvents) -> Unit
) )

View file

@ -44,6 +44,7 @@ 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.AvatarSize
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.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.textcomposer.model.MessageComposerMode
import io.element.android.libraries.textcomposer.model.aTextEditorStateRich import io.element.android.libraries.textcomposer.model.aTextEditorStateRich
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
@ -87,6 +88,7 @@ open class MessagesStateProvider : PreviewParameterProvider<MessagesState> {
), ),
aMessagesState(roomName = AsyncData.Success("A DM with a very looong name"), dmUserVerificationState = IdentityState.Verified), aMessagesState(roomName = AsyncData.Success("A DM with a very looong name"), dmUserVerificationState = IdentityState.Verified),
aMessagesState(roomName = AsyncData.Success("A DM with a very looong name"), dmUserVerificationState = IdentityState.VerificationViolation), aMessagesState(roomName = AsyncData.Success("A DM with a very looong name"), dmUserVerificationState = IdentityState.VerificationViolation),
aMessagesState(successorRoom = SuccessorRoom(RoomId("!id:domain"), null)),
) )
} }
@ -119,6 +121,7 @@ fun aMessagesState(
pinnedMessagesBannerState: PinnedMessagesBannerState = aLoadedPinnedMessagesBannerState(), pinnedMessagesBannerState: PinnedMessagesBannerState = aLoadedPinnedMessagesBannerState(),
dmUserVerificationState: IdentityState? = null, dmUserVerificationState: IdentityState? = null,
roomMemberModerationState: RoomMemberModerationState = aRoomMemberModerationState(), roomMemberModerationState: RoomMemberModerationState = aRoomMemberModerationState(),
successorRoom: SuccessorRoom? = null,
eventSink: (MessagesEvents) -> Unit = {}, eventSink: (MessagesEvents) -> Unit = {},
) = MessagesState( ) = MessagesState(
roomId = RoomId("!id:domain"), roomId = RoomId("!id:domain"),
@ -147,6 +150,7 @@ fun aMessagesState(
pinnedMessagesBannerState = pinnedMessagesBannerState, pinnedMessagesBannerState = pinnedMessagesBannerState,
dmUserVerificationState = dmUserVerificationState, dmUserVerificationState = dmUserVerificationState,
roomMemberModerationState = roomMemberModerationState, roomMemberModerationState = roomMemberModerationState,
successorRoom = successorRoom,
eventSink = eventSink, eventSink = eventSink,
) )

View file

@ -82,6 +82,7 @@ import io.element.android.features.messages.impl.voicemessages.composer.VoiceMes
import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView
import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.libraries.androidutils.ui.hideKeyboard import io.element.android.libraries.androidutils.ui.hideKeyboard
import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertMolecule
import io.element.android.libraries.designsystem.atomic.molecules.IconTitlePlaceholdersRowMolecule import io.element.android.libraries.designsystem.atomic.molecules.IconTitlePlaceholdersRowMolecule
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.AvatarSize
@ -90,6 +91,7 @@ import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
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.theme.components.BottomSheetDragHandle import io.element.android.libraries.designsystem.theme.components.BottomSheetDragHandle
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
@ -101,8 +103,10 @@ import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
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.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
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.textcomposer.model.TextEditorState import io.element.android.libraries.textcomposer.model.TextEditorState
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -211,8 +215,8 @@ fun MessagesView(
onMessageLongClick = ::onMessageLongClick, onMessageLongClick = ::onMessageLongClick,
onUserDataClick = { onUserDataClick = {
hidingKeyboard { hidingKeyboard {
state.eventSink(MessagesEvents.OnUserClicked(it)) state.eventSink(MessagesEvents.OnUserClicked(it))
} }
}, },
onLinkClick = { link, customTab -> onLinkClick = { link, customTab ->
if (customTab) { if (customTab) {
@ -410,6 +414,9 @@ private fun MessagesViewContent(
MessagesViewComposerBottomSheetContents( MessagesViewComposerBottomSheetContents(
subcomposing = subcomposing, subcomposing = subcomposing,
state = state, state = state,
onRoomSuccessorClick = { roomId ->
state.timelineState.eventSink(TimelineEvents.NavigateToRoom(roomId = roomId))
},
onLinkClick = { url, customTab -> onLinkClick(Link(url), customTab) }, onLinkClick = { url, customTab -> onLinkClick(Link(url), customTab) },
) )
}, },
@ -424,52 +431,59 @@ private fun MessagesViewContent(
private fun MessagesViewComposerBottomSheetContents( private fun MessagesViewComposerBottomSheetContents(
subcomposing: Boolean, subcomposing: Boolean,
state: MessagesState, state: MessagesState,
onRoomSuccessorClick: (RoomId) -> Unit,
onLinkClick: (String, Boolean) -> Unit, onLinkClick: (String, Boolean) -> Unit,
) { ) {
if (state.userEventPermissions.canSendMessage) { when {
Column(modifier = Modifier.fillMaxWidth()) { state.successorRoom != null -> {
SuggestionsPickerView( SuccessorRoomBanner(roomSuccessor = state.successorRoom, onRoomSuccessorClick = onRoomSuccessorClick)
modifier = Modifier }
.heightIn(max = 230.dp) state.userEventPermissions.canSendMessage -> {
// Consume all scrolling, preventing the bottom sheet from being dragged when interacting with the list of suggestions Column(modifier = Modifier.fillMaxWidth()) {
.nestedScroll(object : NestedScrollConnection { SuggestionsPickerView(
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset { modifier = Modifier
return available .heightIn(max = 230.dp)
} // Consume all scrolling, preventing the bottom sheet from being dragged when interacting with the list of suggestions
}), .nestedScroll(object : NestedScrollConnection {
roomId = state.roomId, override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
roomName = state.roomName.dataOrNull(), return available
roomAvatarData = state.roomAvatar.dataOrNull(), }
suggestions = state.composerState.suggestions, }),
onSelectSuggestion = { roomId = state.roomId,
state.composerState.eventSink(MessageComposerEvents.InsertSuggestion(it)) roomName = state.roomName.dataOrNull(),
roomAvatarData = state.roomAvatar.dataOrNull(),
suggestions = state.composerState.suggestions,
onSelectSuggestion = {
state.composerState.eventSink(MessageComposerEvents.InsertSuggestion(it))
}
)
// Do not show the identity change if user is composing a Rich message or is seeing suggestion(s).
if (state.composerState.suggestions.isEmpty() &&
state.composerState.textEditorState is TextEditorState.Markdown) {
IdentityChangeStateView(
state = state.identityChangeState,
onLinkClick = onLinkClick,
)
}
val verificationViolation = state.identityChangeState.roomMemberIdentityStateChanges.firstOrNull {
it.identityState == IdentityState.VerificationViolation
}
if (verificationViolation != null) {
DisabledComposerView(modifier = Modifier.fillMaxWidth())
} else {
MessageComposerView(
state = state.composerState,
voiceMessageState = state.voiceMessageComposerState,
subcomposing = subcomposing,
enableVoiceMessages = state.enableVoiceMessages,
modifier = Modifier.fillMaxWidth(),
)
} }
)
// Do not show the identity change if user is composing a Rich message or is seeing suggestion(s).
if (state.composerState.suggestions.isEmpty() &&
state.composerState.textEditorState is TextEditorState.Markdown) {
IdentityChangeStateView(
state = state.identityChangeState,
onLinkClick = onLinkClick,
)
}
val verificationViolation = state.identityChangeState.roomMemberIdentityStateChanges.firstOrNull {
it.identityState == IdentityState.VerificationViolation
}
if (verificationViolation != null) {
DisabledComposerView(modifier = Modifier.fillMaxWidth())
} else {
MessageComposerView(
state = state.composerState,
voiceMessageState = state.voiceMessageComposerState,
subcomposing = subcomposing,
enableVoiceMessages = state.enableVoiceMessages,
modifier = Modifier.fillMaxWidth(),
)
} }
} }
} else { else -> {
CantSendMessageBanner() CantSendMessageBanner()
}
} }
} }
@ -572,9 +586,9 @@ private fun RoomAvatarAndNameRow(
private fun CantSendMessageBanner() { private fun CantSendMessageBanner() {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.background(ElementTheme.colors.bgSubtleSecondary) .background(ElementTheme.colors.bgSubtleSecondary)
.padding(16.dp), .padding(16.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center horizontalArrangement = Arrangement.Center
) { ) {
@ -588,6 +602,22 @@ private fun CantSendMessageBanner() {
} }
} }
@Composable
private fun SuccessorRoomBanner(
roomSuccessor: SuccessorRoom,
onRoomSuccessorClick: (RoomId) -> Unit,
modifier: Modifier = Modifier,
) {
ComposerAlertMolecule(
avatar = null,
content = stringResource(R.string.screen_room_timeline_tombstoned_room_message).toAnnotatedString(),
onSubmitClick = { onRoomSuccessorClick(roomSuccessor.roomId) },
modifier = modifier,
isCritical = false,
submitText = stringResource(R.string.screen_room_timeline_tombstoned_room_action)
)
}
@PreviewsDayNight @PreviewsDayNight
@Composable @Composable
internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class) state: MessagesState) = ElementPreview { internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class) state: MessagesState) = ElementPreview {

View file

@ -106,7 +106,8 @@ class PinnedMessagesListPresenter @AssistedInject constructor(
renderTypingNotifications = false, renderTypingNotifications = false,
typingMembers = persistentListOf(), typingMembers = persistentListOf(),
reserveSpace = false, reserveSpace = false,
) ),
predecessorRoom = room.predecessorRoom(),
) )
} }
val timelineProtectionState = timelineProtectionPresenter.present() val timelineProtectionState = timelineProtectionPresenter.present()

View file

@ -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.

View file

@ -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)
}
} }
} }
@ -257,8 +260,9 @@ class TimelinePresenter @AssistedInject constructor(
userHasPermissionToSendMessage = userHasPermissionToSendMessage, userHasPermissionToSendMessage = userHasPermissionToSendMessage,
userHasPermissionToSendReaction = userHasPermissionToSendReaction, userHasPermissionToSendReaction = userHasPermissionToSendReaction,
roomCallState = roomCallState, roomCallState = roomCallState,
pinnedEventIds = roomInfo.pinnedEventIds.orEmpty(), pinnedEventIds = roomInfo.pinnedEventIds,
typingNotificationState = typingNotificationState, typingNotificationState = typingNotificationState,
predecessorRoom = room.predecessorRoom(),
) )
} }
} }

View file

@ -15,6 +15,7 @@ import io.element.android.features.messages.impl.typing.TypingNotificationState
import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomcall.api.RoomCallState
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.UniqueId import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlin.time.Duration import kotlin.time.Duration
@ -77,4 +78,5 @@ data class TimelineRoomInfo(
val roomCallState: RoomCallState, val roomCallState: RoomCallState,
val pinnedEventIds: List<EventId>, val pinnedEventIds: List<EventId>,
val typingNotificationState: TypingNotificationState, val typingNotificationState: TypingNotificationState,
val predecessorRoom: PredecessorRoom?,
) )

View file

@ -30,6 +30,7 @@ import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.core.TransactionId
import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UniqueId
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.room.tombstone.PredecessorRoom
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
@ -246,6 +247,7 @@ internal fun aTimelineRoomInfo(
userHasPermissionToSendMessage: Boolean = true, userHasPermissionToSendMessage: Boolean = true,
pinnedEventIds: List<EventId> = emptyList(), pinnedEventIds: List<EventId> = emptyList(),
typingNotificationState: TypingNotificationState = aTypingNotificationState(), typingNotificationState: TypingNotificationState = aTypingNotificationState(),
predecessorRoom: PredecessorRoom? = null,
) = TimelineRoomInfo( ) = TimelineRoomInfo(
isDm = isDm, isDm = isDm,
name = name, name = name,
@ -254,4 +256,5 @@ internal fun aTimelineRoomInfo(
roomCallState = aStandByCallState(), roomCallState = aStandByCallState(),
pinnedEventIds = pinnedEventIds, pinnedEventIds = pinnedEventIds,
typingNotificationState = typingNotificationState, typingNotificationState = typingNotificationState,
predecessorRoom = predecessorRoom,
) )

View file

@ -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(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)

View file

@ -7,6 +7,7 @@
package io.element.android.features.messages.impl.timeline.components.virtual package io.element.android.features.messages.impl.timeline.components.virtual
import androidx.compose.foundation.layout.Arrangement.spacedBy
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -19,44 +20,74 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.ElementTheme
import io.element.android.features.messages.impl.R import io.element.android.features.messages.impl.R
import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertMolecule
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.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
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.room.tombstone.PredecessorRoom
@Composable @Composable
fun TimelineItemRoomBeginningView( fun TimelineItemRoomBeginningView(
roomName: String?, roomName: String?,
predecessorRoom: PredecessorRoom?,
onPredecessorRoomClick: (RoomId) -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
Box( Column(
modifier = modifier modifier = modifier.fillMaxWidth()
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
contentAlignment = Alignment.Center,
) { ) {
val text = if (roomName == null) { if (predecessorRoom != null) {
stringResource(id = R.string.screen_room_timeline_beginning_of_room_no_name) ComposerAlertMolecule(
} else { avatar = null,
stringResource(id = R.string.screen_room_timeline_beginning_of_room, roomName) content = stringResource(R.string.screen_room_timeline_upgraded_room_message).toAnnotatedString(),
onSubmitClick = { onPredecessorRoomClick(predecessorRoom.roomId) },
isCritical = false,
submitText = stringResource(R.string.screen_room_timeline_upgraded_room_action)
)
}
Box(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
contentAlignment = Alignment.Center,
) {
val text = if (roomName == null) {
stringResource(id = R.string.screen_room_timeline_beginning_of_room_no_name)
} else {
stringResource(id = R.string.screen_room_timeline_beginning_of_room, roomName)
}
Text(
color = ElementTheme.colors.textSecondary,
style = ElementTheme.typography.fontBodyMdRegular,
text = text,
textAlign = TextAlign.Center,
)
} }
Text(
color = ElementTheme.colors.textSecondary,
style = ElementTheme.typography.fontBodyMdRegular,
text = text,
textAlign = TextAlign.Center,
)
} }
} }
@PreviewsDayNight @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemRoomBeginningViewPreview() = ElementPreview { internal fun TimelineItemRoomBeginningViewPreview() = ElementPreview {
Column { Column(verticalArrangement = spacedBy(16.dp)) {
TimelineItemRoomBeginningView( TimelineItemRoomBeginningView(
predecessorRoom = null,
roomName = null, roomName = null,
onPredecessorRoomClick = {},
) )
TimelineItemRoomBeginningView( TimelineItemRoomBeginningView(
predecessorRoom = null,
roomName = "Room Name", roomName = "Room Name",
onPredecessorRoomClick = {},
)
TimelineItemRoomBeginningView(
predecessorRoom = PredecessorRoom(RoomId("!roomId:matrix.org"), EventId("\$eventId:matrix.org")),
roomName = "Room Name",
onPredecessorRoomClick = {},
) )
} }
} }

View file

@ -43,6 +43,10 @@
<item quantity="few">"%1$d změny místnosti"</item> <item quantity="few">"%1$d změny místnosti"</item>
<item quantity="other">"%1$d změn místnosti"</item> <item quantity="other">"%1$d změn místnosti"</item>
</plurals> </plurals>
<string name="screen_room_timeline_tombstoned_room_action">"Přejít do nové místnosti"</string>
<string name="screen_room_timeline_tombstoned_room_message">"Tato místnost byla nahrazena a již není aktivní"</string>
<string name="screen_room_timeline_upgraded_room_action">"Zobrazit staré zprávy"</string>
<string name="screen_room_timeline_upgraded_room_message">"Tato místnost je pokračováním jiné místnosti"</string>
<plurals name="screen_room_typing_many_members"> <plurals name="screen_room_typing_many_members">
<item quantity="one">"%1$s, %2$s a %3$d další"</item> <item quantity="one">"%1$s, %2$s a %3$d další"</item>
<item quantity="few">"%1$s, %2$s a %3$d další"</item> <item quantity="few">"%1$s, %2$s a %3$d další"</item>

View file

@ -51,6 +51,10 @@
<item quantity="one">"%1$d room change"</item> <item quantity="one">"%1$d room change"</item>
<item quantity="other">"%1$d room changes"</item> <item quantity="other">"%1$d room changes"</item>
</plurals> </plurals>
<string name="screen_room_timeline_tombstoned_room_action">"Jump to new room"</string>
<string name="screen_room_timeline_tombstoned_room_message">"This room has been replaced and is no longer active"</string>
<string name="screen_room_timeline_upgraded_room_action">"See old messages"</string>
<string name="screen_room_timeline_upgraded_room_message">"This room is a continuation of another room"</string>
<plurals name="screen_room_typing_many_members"> <plurals name="screen_room_typing_many_members">
<item quantity="one">"%1$s, %2$s and %3$d other"</item> <item quantity="one">"%1$s, %2$s and %3$d other"</item>
<item quantity="other">"%1$s, %2$s and %3$d others"</item> <item quantity="other">"%1$s, %2$s and %3$d others"</item>

View file

@ -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 io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaError
@ -20,6 +21,7 @@ class FakeMessagesNavigator(
private val onReportContentClickLambda: (eventId: EventId, senderId: UserId) -> Unit = { _, _ -> lambdaError() }, private val onReportContentClickLambda: (eventId: EventId, senderId: UserId) -> Unit = { _, _ -> lambdaError() },
private val onEditPollClickLambda: (eventId: EventId) -> Unit = { _ -> lambdaError() }, private val onEditPollClickLambda: (eventId: EventId) -> Unit = { _ -> lambdaError() },
private val onPreviewAttachmentLambda: (attachments: ImmutableList<Attachment>) -> Unit = { _ -> lambdaError() }, private val onPreviewAttachmentLambda: (attachments: ImmutableList<Attachment>) -> Unit = { _ -> lambdaError() },
private val onNavigateToRoomLambda: (roomId: RoomId) -> Unit = { _ -> lambdaError() }
) : MessagesNavigator { ) : MessagesNavigator {
override fun onShowEventDebugInfoClick(eventId: EventId?, debugInfo: TimelineItemDebugInfo) { override fun onShowEventDebugInfoClick(eventId: EventId?, debugInfo: TimelineItemDebugInfo) {
onShowEventDebugInfoClickLambda(eventId, debugInfo) onShowEventDebugInfoClickLambda(eventId, debugInfo)
@ -40,4 +42,8 @@ class FakeMessagesNavigator(
override fun onPreviewAttachment(attachments: ImmutableList<Attachment>) { override fun onPreviewAttachment(attachments: ImmutableList<Attachment>) {
onPreviewAttachmentLambda(attachments) onPreviewAttachmentLambda(attachments)
} }
override fun onNavigateToRoom(roomId: RoomId) {
onNavigateToRoomLambda(roomId)
}
} }

View file

@ -50,6 +50,7 @@ import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
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.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.MediaSource
@ -57,6 +58,7 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId
@ -1130,6 +1132,57 @@ class MessagesPresenterTest {
} }
} }
@Test
fun `present - room with successor room includes successor info in state`() = runTest {
val successorRoomId = RoomId("!successor:server.org")
val successorReason = "This room has been moved to a new location"
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
initialRoomInfo = aRoomInfo(
successorRoom = SuccessorRoom(
roomId = successorRoomId,
reason = successorReason
)
)
),
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
skipItems(1)
val initialState = awaitItem()
assertThat(initialState.successorRoom).isNotNull()
assertThat(initialState.successorRoom?.roomId).isEqualTo(successorRoomId)
assertThat(initialState.successorRoom?.reason).isEqualTo(successorReason)
}
}
@Test
fun `present - room without successor room has null successor info in state`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
initialRoomInfo = aRoomInfo(successorRoom = null)
),
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
skipItems(1)
val initialState = awaitItem()
assertThat(initialState.successorRoom).isNull()
}
}
@Test @Test
fun `present - when room is encrypted and a DM, the DM user's identity state is fetched onResume`() = runTest { fun `present - when room is encrypted and a DM, the DM user's identity state is fetched onResume`() = runTest {
val room = FakeJoinedRoom( val room = FakeJoinedRoom(

View file

@ -52,7 +52,9 @@ import io.element.android.features.messages.impl.timeline.components.receipt.aRe
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents
import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
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.room.tombstone.SuccessorRoom
import io.element.android.libraries.matrix.api.timeline.item.event.getAvatarUrl import io.element.android.libraries.matrix.api.timeline.item.event.getAvatarUrl
import io.element.android.libraries.matrix.api.timeline.item.event.getDisplayName import io.element.android.libraries.matrix.api.timeline.item.event.getDisplayName
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
@ -65,6 +67,7 @@ import io.element.android.tests.testutils.EnsureNeverCalledWithParam
import io.element.android.tests.testutils.EnsureNeverCalledWithTwoParams import io.element.android.tests.testutils.EnsureNeverCalledWithTwoParams
import io.element.android.tests.testutils.EnsureNeverCalledWithTwoParamsAndResult import io.element.android.tests.testutils.EnsureNeverCalledWithTwoParamsAndResult
import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.assertNoNodeWithText
import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.clickOn
import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.ensureCalledOnce
import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressBack
@ -560,6 +563,36 @@ class MessagesViewTest {
rule.onNodeWithText("This is a pinned message").performClick() rule.onNodeWithText("This is a pinned message").performClick()
eventsRecorder.assertSingle(TimelineEvents.FocusOnEvent(AN_EVENT_ID, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds)) eventsRecorder.assertSingle(TimelineEvents.FocusOnEvent(AN_EVENT_ID, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds))
} }
@Test
fun `clicking on successor room button emits expected event`() {
val eventsRecorder = EventsRecorder<TimelineEvents>()
val successorRoomId = RoomId("!successor:server.org")
val state = aMessagesState(
successorRoom = SuccessorRoom(
roomId = successorRoomId,
reason = "This room has been upgraded"
),
timelineState = aTimelineState(eventSink = eventsRecorder)
)
rule.setMessagesView(state = state)
val text = rule.activity.getString(R.string.screen_room_timeline_tombstoned_room_action)
// The bottomsheet subcompose seems to make the node to appear twice
rule.onAllNodesWithText(text).onFirst().performClick()
eventsRecorder.assertSingle(TimelineEvents.NavigateToRoom(successorRoomId))
}
@Test
fun `no banner shown when there is no successor room`() {
val eventsRecorder = EventsRecorder<MessagesEvents>(expectEvents = false)
val state = aMessagesState(
successorRoom = null,
eventSink = eventsRecorder
)
rule.setMessagesView(state = state)
rule.assertNoNodeWithText(R.string.screen_room_timeline_tombstoned_room_message)
rule.assertNoNodeWithText(R.string.screen_room_timeline_tombstoned_room_action)
}
} }
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setMessagesView( private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setMessagesView(

View file

@ -32,6 +32,7 @@ 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.UniqueId import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.Timeline
@ -64,6 +65,7 @@ import io.element.android.tests.testutils.test
import io.element.android.tests.testutils.testCoroutineDispatchers import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
@ -80,7 +82,7 @@ import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@Suppress("LargeClass") @Suppress("LargeClass")
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
class TimelinePresenterTest { class TimelinePresenterTest {
@get:Rule @get:Rule
val warmUpRule = WarmUpRule() val warmUpRule = WarmUpRule()
@ -705,6 +707,73 @@ class TimelinePresenterTest {
} }
} }
@Test
fun `present - timeline room info includes predecessor room when room has predecessor`() = runTest {
val predecessorRoomId = RoomId("!predecessor:server.org")
val predecessorEventId = EventId("\$predecessorEvent:server.org")
val predecessorRoom = PredecessorRoom(
roomId = predecessorRoomId,
lastEventId = predecessorEventId
)
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
predecessorRoomResult = { predecessorRoom }
),
)
val presenter = createTimelinePresenter(room = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitFirstItem()
assertThat(initialState.timelineRoomInfo.predecessorRoom).isNotNull()
assertThat(initialState.timelineRoomInfo.predecessorRoom?.roomId).isEqualTo(predecessorRoomId)
assertThat(initialState.timelineRoomInfo.predecessorRoom?.lastEventId).isEqualTo(predecessorEventId)
}
}
@Test
fun `present - timeline room info no predecessor`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
predecessorRoomResult = { null }
),
)
val presenter = createTimelinePresenter(room = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitFirstItem()
assertThat(initialState.timelineRoomInfo.predecessorRoom).isNull()
}
}
@Test
fun `present - timeline event navigate to room`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
),
)
val onNavigateToRoomLambda = lambdaRecorder<RoomId, Unit> {}
val navigator = FakeMessagesNavigator(
onNavigateToRoomLambda = onNavigateToRoomLambda
)
val presenter = createTimelinePresenter(room = room, messagesNavigator = navigator)
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink(TimelineEvents.NavigateToRoom(A_ROOM_ID))
assert(onNavigateToRoomLambda)
.isCalledOnce()
.with(
value(A_ROOM_ID)
)
}
}
private suspend fun <T> ReceiveTurbine<T>.awaitFirstItem(): T { private suspend fun <T> ReceiveTurbine<T>.awaitFirstItem(): T {
return awaitItem() return awaitItem()
} }

View file

@ -148,7 +148,7 @@ internal fun RoomSummaryRow(
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
} }
Text( Text(
text = stringResource(id = R.string.screen_join_room_knock_sent_title), text = stringResource(id = R.string.screen_roomlist_knock_event_sent_description),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
style = ElementTheme.typography.fontBodyMdRegular, style = ElementTheme.typography.fontBodyMdRegular,

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Odmítnout chat"</string> <string name="screen_invites_decline_direct_chat_title">"Odmítnout chat"</string>
<string name="screen_invites_empty_list">"Žádné pozvánky"</string> <string name="screen_invites_empty_list">"Žádné pozvánky"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) vás pozval(a)"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) vás pozval(a)"</string>
<string name="screen_join_room_knock_sent_title">"Žádost o vstup odeslána"</string>
<string name="screen_migration_message">"Jedná se o jednorázový proces, prosíme o strpení."</string> <string name="screen_migration_message">"Jedná se o jednorázový proces, prosíme o strpení."</string>
<string name="screen_migration_title">"Nastavení vašeho účtu"</string> <string name="screen_migration_title">"Nastavení vašeho účtu"</string>
<string name="screen_roomlist_a11y_create_message">"Vytvořte novou konverzaci nebo místnost"</string> <string name="screen_roomlist_a11y_create_message">"Vytvořte novou konverzaci nebo místnost"</string>
@ -37,9 +36,11 @@ Prozatím můžete zrušit výběr filtrů, abyste viděli své další chaty"</
<string name="screen_roomlist_filter_unreads">"Nepřečtené"</string> <string name="screen_roomlist_filter_unreads">"Nepřečtené"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Gratulujeme! <string name="screen_roomlist_filter_unreads_empty_state_title">"Gratulujeme!
Nemáte žádné nepřečtené zprávy!"</string> Nemáte žádné nepřečtené zprávy!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Žádost o vstup odeslána"</string>
<string name="screen_roomlist_main_space_title">"Všechny chaty"</string> <string name="screen_roomlist_main_space_title">"Všechny chaty"</string>
<string name="screen_roomlist_mark_as_read">"Označit jako přečtené"</string> <string name="screen_roomlist_mark_as_read">"Označit jako přečtené"</string>
<string name="screen_roomlist_mark_as_unread">"Označit jako nepřečtené"</string> <string name="screen_roomlist_mark_as_unread">"Označit jako nepřečtené"</string>
<string name="screen_roomlist_tombstoned_room_description">"Tato místnost byla aktualizována"</string>
<string name="session_verification_banner_message">"Zdá se, že používáte nové zařízení. Ověřte přihlášení, abyste měli přístup k zašifrovaným zprávám."</string> <string name="session_verification_banner_message">"Zdá se, že používáte nové zařízení. Ověřte přihlášení, abyste měli přístup k zašifrovaným zprávám."</string>
<string name="session_verification_banner_title">"Ověřte, že jste to vy"</string> <string name="session_verification_banner_title">"Ověřte, že jste to vy"</string>
</resources> </resources>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Gwrthod sgwrs"</string> <string name="screen_invites_decline_direct_chat_title">"Gwrthod sgwrs"</string>
<string name="screen_invites_empty_list">"Dim Gwahoddiadau"</string> <string name="screen_invites_empty_list">"Dim Gwahoddiadau"</string>
<string name="screen_invites_invited_you">"Mae %1$s (%2$s) wedi eich gwahodd"</string> <string name="screen_invites_invited_you">"Mae %1$s (%2$s) wedi eich gwahodd"</string>
<string name="screen_join_room_knock_sent_title">"Anfonwyd y cais i ymuno"</string>
<string name="screen_migration_message">"Mae hon yn broses un tro, diolch am aros."</string> <string name="screen_migration_message">"Mae hon yn broses un tro, diolch am aros."</string>
<string name="screen_migration_title">"Creu eich cyfrif."</string> <string name="screen_migration_title">"Creu eich cyfrif."</string>
<string name="screen_roomlist_a11y_create_message">"Crëwch sgwrs neu ystafell newydd"</string> <string name="screen_roomlist_a11y_create_message">"Crëwch sgwrs neu ystafell newydd"</string>
@ -37,6 +36,7 @@ Am y tro, gallwch ddad-ddewis hidlwyr er mwyn gweld eich sgyrsiau eraill"</strin
<string name="screen_roomlist_filter_unreads">"Heb ei ddarllen"</string> <string name="screen_roomlist_filter_unreads">"Heb ei ddarllen"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Llongyfarchiadau! <string name="screen_roomlist_filter_unreads_empty_state_title">"Llongyfarchiadau!
Does gennych chi ddim negeseuon heb eu darllen!"</string> Does gennych chi ddim negeseuon heb eu darllen!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Anfonwyd y cais i ymuno"</string>
<string name="screen_roomlist_main_space_title">"Sgyrsiau"</string> <string name="screen_roomlist_main_space_title">"Sgyrsiau"</string>
<string name="screen_roomlist_mark_as_read">"Marcio fel wedi\'i ddarllen"</string> <string name="screen_roomlist_mark_as_read">"Marcio fel wedi\'i ddarllen"</string>
<string name="screen_roomlist_mark_as_unread">"Marcio fel heb ei ddarllen"</string> <string name="screen_roomlist_mark_as_unread">"Marcio fel heb ei ddarllen"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Einladung ablehnen"</string> <string name="screen_invites_decline_direct_chat_title">"Einladung ablehnen"</string>
<string name="screen_invites_empty_list">"Keine Einladungen"</string> <string name="screen_invites_empty_list">"Keine Einladungen"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) hat dich eingeladen"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) hat dich eingeladen"</string>
<string name="screen_join_room_knock_sent_title">"Beitrittsanfrage geschickt"</string>
<string name="screen_migration_message">"Dies ist ein einmaliger Vorgang, danke fürs Warten."</string> <string name="screen_migration_message">"Dies ist ein einmaliger Vorgang, danke fürs Warten."</string>
<string name="screen_migration_title">"Dein Konto wird eingerichtet."</string> <string name="screen_migration_title">"Dein Konto wird eingerichtet."</string>
<string name="screen_roomlist_a11y_create_message">"Eine Unterthaltung oder Raum erstellen"</string> <string name="screen_roomlist_a11y_create_message">"Eine Unterthaltung oder Raum erstellen"</string>
@ -37,6 +36,7 @@ Deaktivieren Sie den entsprechenden Filter, um Ihre anderen Chatrooms zu sehen"<
<string name="screen_roomlist_filter_unreads">"Ungelesen"</string> <string name="screen_roomlist_filter_unreads">"Ungelesen"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Glückwunsch! <string name="screen_roomlist_filter_unreads_empty_state_title">"Glückwunsch!
Sie haben keine ungelesenen Nachrichten!"</string> Sie haben keine ungelesenen Nachrichten!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Beitrittsanfrage geschickt"</string>
<string name="screen_roomlist_main_space_title">"Chats"</string> <string name="screen_roomlist_main_space_title">"Chats"</string>
<string name="screen_roomlist_mark_as_read">"Als gelesen markieren"</string> <string name="screen_roomlist_mark_as_read">"Als gelesen markieren"</string>
<string name="screen_roomlist_mark_as_unread">"Als ungelesen markieren"</string> <string name="screen_roomlist_mark_as_unread">"Als ungelesen markieren"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Απόρριψη συνομιλίας"</string> <string name="screen_invites_decline_direct_chat_title">"Απόρριψη συνομιλίας"</string>
<string name="screen_invites_empty_list">"Χωρίς προσκλήσεις"</string> <string name="screen_invites_empty_list">"Χωρίς προσκλήσεις"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) σέ προσκάλεσε"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) σέ προσκάλεσε"</string>
<string name="screen_join_room_knock_sent_title">"Το αίτημα συμμετοχής στάλθηκε"</string>
<string name="screen_migration_message">"Αυτή είναι μια εφάπαξ διαδικασία, ευχαριστώ που περίμενες."</string> <string name="screen_migration_message">"Αυτή είναι μια εφάπαξ διαδικασία, ευχαριστώ που περίμενες."</string>
<string name="screen_migration_title">"Ρύθμιση του λογαριασμού σου."</string> <string name="screen_migration_title">"Ρύθμιση του λογαριασμού σου."</string>
<string name="screen_roomlist_a11y_create_message">"Δημιουργία νέας συνομιλίας ή δωματίου"</string> <string name="screen_roomlist_a11y_create_message">"Δημιουργία νέας συνομιλίας ή δωματίου"</string>
@ -37,6 +36,7 @@
<string name="screen_roomlist_filter_unreads">"Μη αναγνωσμένα"</string> <string name="screen_roomlist_filter_unreads">"Μη αναγνωσμένα"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Συγχαρητήρια! <string name="screen_roomlist_filter_unreads_empty_state_title">"Συγχαρητήρια!
Δεν έχεις μη αναγνωσμένα μηνύματα!"</string> Δεν έχεις μη αναγνωσμένα μηνύματα!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Το αίτημα συμμετοχής στάλθηκε"</string>
<string name="screen_roomlist_main_space_title">"Συνομιλίες"</string> <string name="screen_roomlist_main_space_title">"Συνομιλίες"</string>
<string name="screen_roomlist_mark_as_read">"Επισήμανση ως αναγνωσμένου"</string> <string name="screen_roomlist_mark_as_read">"Επισήμανση ως αναγνωσμένου"</string>
<string name="screen_roomlist_mark_as_unread">"Επισήμανση ως μη αναγνωσμένου"</string> <string name="screen_roomlist_mark_as_unread">"Επισήμανση ως μη αναγνωσμένου"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Rechazar el chat"</string> <string name="screen_invites_decline_direct_chat_title">"Rechazar el chat"</string>
<string name="screen_invites_empty_list">"Sin invitaciones"</string> <string name="screen_invites_empty_list">"Sin invitaciones"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) te invitó"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) te invitó"</string>
<string name="screen_join_room_knock_sent_title">"Solicitud de unión enviada"</string>
<string name="screen_migration_message">"Este proceso solo se hace una vez, gracias por esperar."</string> <string name="screen_migration_message">"Este proceso solo se hace una vez, gracias por esperar."</string>
<string name="screen_migration_title">"Configura tu cuenta"</string> <string name="screen_migration_title">"Configura tu cuenta"</string>
<string name="screen_roomlist_a11y_create_message">"Crear una nueva conversación o sala"</string> <string name="screen_roomlist_a11y_create_message">"Crear una nueva conversación o sala"</string>
@ -37,6 +36,7 @@ Por ahora, puedes deseleccionar los filtros para ver tus otros chats"</string>
<string name="screen_roomlist_filter_unreads">"No leídos"</string> <string name="screen_roomlist_filter_unreads">"No leídos"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"¡Felicidades! <string name="screen_roomlist_filter_unreads_empty_state_title">"¡Felicidades!
¡No tienes ningún mensaje sin leer!"</string> ¡No tienes ningún mensaje sin leer!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Solicitud de unión enviada"</string>
<string name="screen_roomlist_main_space_title">"Chats"</string> <string name="screen_roomlist_main_space_title">"Chats"</string>
<string name="screen_roomlist_mark_as_read">"Marcar como leído"</string> <string name="screen_roomlist_mark_as_read">"Marcar como leído"</string>
<string name="screen_roomlist_mark_as_unread">"Marcar como no leído"</string> <string name="screen_roomlist_mark_as_unread">"Marcar como no leído"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Keeldu vestlusest"</string> <string name="screen_invites_decline_direct_chat_title">"Keeldu vestlusest"</string>
<string name="screen_invites_empty_list">"Kutseid pole"</string> <string name="screen_invites_empty_list">"Kutseid pole"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) saatis sulle kutse"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) saatis sulle kutse"</string>
<string name="screen_join_room_knock_sent_title">"Liitumispalve on saadetud"</string>
<string name="screen_migration_message">"Tänud, et ootad - seda toimingut on vaja teha vaid üks kord."</string> <string name="screen_migration_message">"Tänud, et ootad - seda toimingut on vaja teha vaid üks kord."</string>
<string name="screen_migration_title">"Seadistame sinu kasutajakontot."</string> <string name="screen_migration_title">"Seadistame sinu kasutajakontot."</string>
<string name="screen_roomlist_a11y_create_message">"Loo uus vestlus või jututuba"</string> <string name="screen_roomlist_a11y_create_message">"Loo uus vestlus või jututuba"</string>
@ -37,6 +36,7 @@ Aga seni… oma teiste vestluste nägemiseks pead eemaldama filtrid"</string>
<string name="screen_roomlist_filter_unreads">"Lugemata"</string> <string name="screen_roomlist_filter_unreads">"Lugemata"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Õnnitleme! <string name="screen_roomlist_filter_unreads_empty_state_title">"Õnnitleme!
Sul pole ühtegi lugemata sõnumit!"</string> Sul pole ühtegi lugemata sõnumit!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Liitumispalve on saadetud"</string>
<string name="screen_roomlist_main_space_title">"Vestlused"</string> <string name="screen_roomlist_main_space_title">"Vestlused"</string>
<string name="screen_roomlist_mark_as_read">"Märgi loetuks"</string> <string name="screen_roomlist_mark_as_read">"Märgi loetuks"</string>
<string name="screen_roomlist_mark_as_unread">"Märgi mitteloetuks"</string> <string name="screen_roomlist_mark_as_unread">"Märgi mitteloetuks"</string>

View file

@ -11,7 +11,6 @@
<string name="screen_invites_decline_direct_chat_title">"Baztertu txata"</string> <string name="screen_invites_decline_direct_chat_title">"Baztertu txata"</string>
<string name="screen_invites_empty_list">"Ez dago gonbidapenik"</string> <string name="screen_invites_empty_list">"Ez dago gonbidapenik"</string>
<string name="screen_invites_invited_you">"%1$s(e)k (%2$s) gonbidatu zaitu"</string> <string name="screen_invites_invited_you">"%1$s(e)k (%2$s) gonbidatu zaitu"</string>
<string name="screen_join_room_knock_sent_title">"Sartzeko eskaera bidali da"</string>
<string name="screen_migration_message">"Behin egin beharreko prozesua da; eskerrik asko itxaroteagatik."</string> <string name="screen_migration_message">"Behin egin beharreko prozesua da; eskerrik asko itxaroteagatik."</string>
<string name="screen_migration_title">"Zure kontua konfiguratzen."</string> <string name="screen_migration_title">"Zure kontua konfiguratzen."</string>
<string name="screen_roomlist_a11y_create_message">"Sortu elkarrizketa edo gela berria"</string> <string name="screen_roomlist_a11y_create_message">"Sortu elkarrizketa edo gela berria"</string>
@ -33,6 +32,7 @@ Oraingoz, iragazkiak desautatu ditzakezu zure gainerako txatak ikusteko"</string
<string name="screen_roomlist_filter_unreads">"Irakurri gabeak"</string> <string name="screen_roomlist_filter_unreads">"Irakurri gabeak"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Bejondeizula! <string name="screen_roomlist_filter_unreads_empty_state_title">"Bejondeizula!
Ez duzu irakurri gabeko mezurik!"</string> Ez duzu irakurri gabeko mezurik!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Sartzeko eskaera bidali da"</string>
<string name="screen_roomlist_main_space_title">"Txatak"</string> <string name="screen_roomlist_main_space_title">"Txatak"</string>
<string name="screen_roomlist_mark_as_read">"Markatu irakurritzat"</string> <string name="screen_roomlist_mark_as_read">"Markatu irakurritzat"</string>
<string name="screen_roomlist_mark_as_unread">"Markatu irakurri gabetzat"</string> <string name="screen_roomlist_mark_as_unread">"Markatu irakurri gabetzat"</string>

View file

@ -11,7 +11,6 @@
<string name="screen_invites_decline_direct_chat_title">"رد گپ"</string> <string name="screen_invites_decline_direct_chat_title">"رد گپ"</string>
<string name="screen_invites_empty_list">"بدون دعوت"</string> <string name="screen_invites_empty_list">"بدون دعوت"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) دعوتتان کرد"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) دعوتتان کرد"</string>
<string name="screen_join_room_knock_sent_title">"درخواست پیوستن فرستاده شد"</string>
<string name="screen_migration_message">"فرایندی یک باره است. ممنون از شکیباییتان."</string> <string name="screen_migration_message">"فرایندی یک باره است. ممنون از شکیباییتان."</string>
<string name="screen_migration_title">"برپایی حسابتان."</string> <string name="screen_migration_title">"برپایی حسابتان."</string>
<string name="screen_roomlist_a11y_create_message">"ایجاد اتاق یا گفت‌وگویی جدید"</string> <string name="screen_roomlist_a11y_create_message">"ایجاد اتاق یا گفت‌وگویی جدید"</string>
@ -31,6 +30,7 @@
<string name="screen_roomlist_filter_unreads">"نخوانده‌ها"</string> <string name="screen_roomlist_filter_unreads">"نخوانده‌ها"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"تبریک! <string name="screen_roomlist_filter_unreads_empty_state_title">"تبریک!
هیچ پیام نخوانده‌ای ندارید!"</string> هیچ پیام نخوانده‌ای ندارید!"</string>
<string name="screen_roomlist_knock_event_sent_description">"درخواست پیوستن فرستاده شد"</string>
<string name="screen_roomlist_main_space_title">"گپ‌ها"</string> <string name="screen_roomlist_main_space_title">"گپ‌ها"</string>
<string name="screen_roomlist_mark_as_read">"علامت‌گذاری به عنوان خوانده شده"</string> <string name="screen_roomlist_mark_as_read">"علامت‌گذاری به عنوان خوانده شده"</string>
<string name="screen_roomlist_mark_as_unread">"نشان به ناخوانده"</string> <string name="screen_roomlist_mark_as_unread">"نشان به ناخوانده"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Hylkää keskustelu"</string> <string name="screen_invites_decline_direct_chat_title">"Hylkää keskustelu"</string>
<string name="screen_invites_empty_list">"Ei kutsuja"</string> <string name="screen_invites_empty_list">"Ei kutsuja"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) kutsui sinut"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) kutsui sinut"</string>
<string name="screen_join_room_knock_sent_title">"Liittymispyyntö lähetetty"</string>
<string name="screen_migration_message">"Tämä on kertaluonteinen prosessi, kiitos odottamisesta."</string> <string name="screen_migration_message">"Tämä on kertaluonteinen prosessi, kiitos odottamisesta."</string>
<string name="screen_migration_title">"Tiliä määritetään."</string> <string name="screen_migration_title">"Tiliä määritetään."</string>
<string name="screen_roomlist_a11y_create_message">"Luo uusi keskustelu tai huone"</string> <string name="screen_roomlist_a11y_create_message">"Luo uusi keskustelu tai huone"</string>
@ -37,6 +36,7 @@ Toistaiseksi voit poistaa suodattimien valinnan, jotta näet muut keskustelut."<
<string name="screen_roomlist_filter_unreads">"Lukemattomat"</string> <string name="screen_roomlist_filter_unreads">"Lukemattomat"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Onnittelut! <string name="screen_roomlist_filter_unreads_empty_state_title">"Onnittelut!
Sinulla ei ole lukemattomia viestejä!"</string> Sinulla ei ole lukemattomia viestejä!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Liittymispyyntö lähetetty"</string>
<string name="screen_roomlist_main_space_title">"Keskustelut"</string> <string name="screen_roomlist_main_space_title">"Keskustelut"</string>
<string name="screen_roomlist_mark_as_read">"Merkitse luetuksi"</string> <string name="screen_roomlist_mark_as_read">"Merkitse luetuksi"</string>
<string name="screen_roomlist_mark_as_unread">"Merkitse lukemattomaksi"</string> <string name="screen_roomlist_mark_as_unread">"Merkitse lukemattomaksi"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Refuser linvitation"</string> <string name="screen_invites_decline_direct_chat_title">"Refuser linvitation"</string>
<string name="screen_invites_empty_list">"Aucune invitation"</string> <string name="screen_invites_empty_list">"Aucune invitation"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) vous a invité(e)"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) vous a invité(e)"</string>
<string name="screen_join_room_knock_sent_title">"Demande de rejoindre le salon envoyée"</string>
<string name="screen_migration_message">"Il sagit dune opération ponctuelle, merci dattendre quelques instants."</string> <string name="screen_migration_message">"Il sagit dune opération ponctuelle, merci dattendre quelques instants."</string>
<string name="screen_migration_title">"Configuration de votre compte."</string> <string name="screen_migration_title">"Configuration de votre compte."</string>
<string name="screen_roomlist_a11y_create_message">"Créer une nouvelle discussion ou un nouveau salon"</string> <string name="screen_roomlist_a11y_create_message">"Créer une nouvelle discussion ou un nouveau salon"</string>
@ -37,6 +36,7 @@ En attendant, vous pouvez désélectionner des filtres pour voir vos autres salo
<string name="screen_roomlist_filter_unreads">"Non-lus"</string> <string name="screen_roomlist_filter_unreads">"Non-lus"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Félicitations ! <string name="screen_roomlist_filter_unreads_empty_state_title">"Félicitations !
Vous navez plus de messages non-lus !"</string> Vous navez plus de messages non-lus !"</string>
<string name="screen_roomlist_knock_event_sent_description">"Demande de rejoindre le salon envoyée"</string>
<string name="screen_roomlist_main_space_title">"Conversations"</string> <string name="screen_roomlist_main_space_title">"Conversations"</string>
<string name="screen_roomlist_mark_as_read">"Marquer comme lu"</string> <string name="screen_roomlist_mark_as_read">"Marquer comme lu"</string>
<string name="screen_roomlist_mark_as_unread">"Marquer comme non lu"</string> <string name="screen_roomlist_mark_as_unread">"Marquer comme non lu"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Csevegés elutasítása"</string> <string name="screen_invites_decline_direct_chat_title">"Csevegés elutasítása"</string>
<string name="screen_invites_empty_list">"Nincsenek meghívások"</string> <string name="screen_invites_empty_list">"Nincsenek meghívások"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) meghívta"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) meghívta"</string>
<string name="screen_join_room_knock_sent_title">"Csatlakozási kérés elküldve"</string>
<string name="screen_migration_message">"Ez egy egyszeri folyamat, köszönjük a türelmét."</string> <string name="screen_migration_message">"Ez egy egyszeri folyamat, köszönjük a türelmét."</string>
<string name="screen_migration_title">"A fiók beállítása."</string> <string name="screen_migration_title">"A fiók beállítása."</string>
<string name="screen_roomlist_a11y_create_message">"Új beszélgetés vagy szoba létrehozása"</string> <string name="screen_roomlist_a11y_create_message">"Új beszélgetés vagy szoba létrehozása"</string>
@ -37,6 +36,7 @@ Egyelőre törölheti a szűrőket a többi csevegés megtekintéséhez."</strin
<string name="screen_roomlist_filter_unreads">"Olvasatlan"</string> <string name="screen_roomlist_filter_unreads">"Olvasatlan"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Gratulálunk! <string name="screen_roomlist_filter_unreads_empty_state_title">"Gratulálunk!
Nincs olvasatlan üzenete!"</string> Nincs olvasatlan üzenete!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Csatlakozási kérés elküldve"</string>
<string name="screen_roomlist_main_space_title">"Összes csevegés"</string> <string name="screen_roomlist_main_space_title">"Összes csevegés"</string>
<string name="screen_roomlist_mark_as_read">"Megjelölés olvasottként"</string> <string name="screen_roomlist_mark_as_read">"Megjelölés olvasottként"</string>
<string name="screen_roomlist_mark_as_unread">"Megjelölés olvasatlanként"</string> <string name="screen_roomlist_mark_as_unread">"Megjelölés olvasatlanként"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Tolak obrolan"</string> <string name="screen_invites_decline_direct_chat_title">"Tolak obrolan"</string>
<string name="screen_invites_empty_list">"Tidak ada undangan"</string> <string name="screen_invites_empty_list">"Tidak ada undangan"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) mengundang Anda"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) mengundang Anda"</string>
<string name="screen_join_room_knock_sent_title">"Permintaan untuk bergabung dikirim"</string>
<string name="screen_migration_message">"Ini adalah proses satu kali, terima kasih telah menunggu."</string> <string name="screen_migration_message">"Ini adalah proses satu kali, terima kasih telah menunggu."</string>
<string name="screen_migration_title">"Menyiapkan akun Anda."</string> <string name="screen_migration_title">"Menyiapkan akun Anda."</string>
<string name="screen_roomlist_a11y_create_message">"Buat percakapan atau ruangan baru"</string> <string name="screen_roomlist_a11y_create_message">"Buat percakapan atau ruangan baru"</string>
@ -37,6 +36,7 @@ Untuk sementara, Anda dapat membatalkan pilihan saringan untuk melihat percakapa
<string name="screen_roomlist_filter_unreads">"Belum dibaca"</string> <string name="screen_roomlist_filter_unreads">"Belum dibaca"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Selamat! <string name="screen_roomlist_filter_unreads_empty_state_title">"Selamat!
Anda tidak memiliki pesan yang belum dibaca!"</string> Anda tidak memiliki pesan yang belum dibaca!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Permintaan untuk bergabung dikirim"</string>
<string name="screen_roomlist_main_space_title">"Semua Obrolan"</string> <string name="screen_roomlist_main_space_title">"Semua Obrolan"</string>
<string name="screen_roomlist_mark_as_read">"Tandai sebagai dibaca"</string> <string name="screen_roomlist_mark_as_read">"Tandai sebagai dibaca"</string>
<string name="screen_roomlist_mark_as_unread">"Tandai sebagai belum dibaca"</string> <string name="screen_roomlist_mark_as_unread">"Tandai sebagai belum dibaca"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Rifiuta l\'invito alla conversazione"</string> <string name="screen_invites_decline_direct_chat_title">"Rifiuta l\'invito alla conversazione"</string>
<string name="screen_invites_empty_list">"Nessun invito"</string> <string name="screen_invites_empty_list">"Nessun invito"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) ti ha invitato"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) ti ha invitato"</string>
<string name="screen_join_room_knock_sent_title">"Richiesta di accesso inviata"</string>
<string name="screen_migration_message">"Si tratta di una procedura che si effettua una sola volta, grazie per l\'attesa."</string> <string name="screen_migration_message">"Si tratta di una procedura che si effettua una sola volta, grazie per l\'attesa."</string>
<string name="screen_migration_title">"Configurazione del tuo account."</string> <string name="screen_migration_title">"Configurazione del tuo account."</string>
<string name="screen_roomlist_a11y_create_message">"Crea una nuova conversazione o stanza"</string> <string name="screen_roomlist_a11y_create_message">"Crea una nuova conversazione o stanza"</string>
@ -37,6 +36,7 @@ Per il momento, puoi deselezionare i filtri per vedere le altre conversazioni."<
<string name="screen_roomlist_filter_unreads">"Non letti"</string> <string name="screen_roomlist_filter_unreads">"Non letti"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Congratulazioni! <string name="screen_roomlist_filter_unreads_empty_state_title">"Congratulazioni!
Non hai messaggi non letti!"</string> Non hai messaggi non letti!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Richiesta di accesso inviata"</string>
<string name="screen_roomlist_main_space_title">"Tutte le conversazioni"</string> <string name="screen_roomlist_main_space_title">"Tutte le conversazioni"</string>
<string name="screen_roomlist_mark_as_read">"Segna come letto"</string> <string name="screen_roomlist_mark_as_read">"Segna come letto"</string>
<string name="screen_roomlist_mark_as_unread">"Segna come non letto"</string> <string name="screen_roomlist_mark_as_unread">"Segna come non letto"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Avslå chat"</string> <string name="screen_invites_decline_direct_chat_title">"Avslå chat"</string>
<string name="screen_invites_empty_list">"Ingen invitasjoner"</string> <string name="screen_invites_empty_list">"Ingen invitasjoner"</string>
<string name="screen_invites_invited_you">"%1$s(%2$s) inviterte deg"</string> <string name="screen_invites_invited_you">"%1$s(%2$s) inviterte deg"</string>
<string name="screen_join_room_knock_sent_title">"Forespørsel om å bli med sendt"</string>
<string name="screen_migration_message">"Dette er en engangsprosess, takk for at du venter."</string> <string name="screen_migration_message">"Dette er en engangsprosess, takk for at du venter."</string>
<string name="screen_migration_title">"Setter opp kontoen din."</string> <string name="screen_migration_title">"Setter opp kontoen din."</string>
<string name="screen_roomlist_a11y_create_message">"Opprett en ny samtale eller et nytt rom"</string> <string name="screen_roomlist_a11y_create_message">"Opprett en ny samtale eller et nytt rom"</string>
@ -37,6 +36,7 @@ Inntil videre kan du velge bort filtre for å se de andre chattene dine"</string
<string name="screen_roomlist_filter_unreads">"Uleste"</string> <string name="screen_roomlist_filter_unreads">"Uleste"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Gratulerer! <string name="screen_roomlist_filter_unreads_empty_state_title">"Gratulerer!
Du har ingen uleste meldinger!"</string> Du har ingen uleste meldinger!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Forespørsel om å bli med sendt"</string>
<string name="screen_roomlist_main_space_title">"Chatter"</string> <string name="screen_roomlist_main_space_title">"Chatter"</string>
<string name="screen_roomlist_mark_as_read">"Marker som lest"</string> <string name="screen_roomlist_mark_as_read">"Marker som lest"</string>
<string name="screen_roomlist_mark_as_unread">"Merk som ulest"</string> <string name="screen_roomlist_mark_as_unread">"Merk som ulest"</string>

View file

@ -13,7 +13,6 @@
<string name="screen_invites_decline_direct_chat_title">"Chat weigeren"</string> <string name="screen_invites_decline_direct_chat_title">"Chat weigeren"</string>
<string name="screen_invites_empty_list">"Geen uitnodigingen"</string> <string name="screen_invites_empty_list">"Geen uitnodigingen"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) heeft je uitgenodigd"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) heeft je uitgenodigd"</string>
<string name="screen_join_room_knock_sent_title">"Verzoek om toe te treden verzonden"</string>
<string name="screen_migration_message">"Dit is een eenmalig proces, bedankt voor het wachten."</string> <string name="screen_migration_message">"Dit is een eenmalig proces, bedankt voor het wachten."</string>
<string name="screen_migration_title">"Je account instellen."</string> <string name="screen_migration_title">"Je account instellen."</string>
<string name="screen_roomlist_a11y_create_message">"Begin een nieuw gesprek of maak een nieuwe kamer"</string> <string name="screen_roomlist_a11y_create_message">"Begin een nieuw gesprek of maak een nieuwe kamer"</string>
@ -35,6 +34,7 @@ Voor nu kun je filters deselecteren om je andere chats te zien"</string>
<string name="screen_roomlist_filter_unreads">"Ongelezen"</string> <string name="screen_roomlist_filter_unreads">"Ongelezen"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Gefeliciteerd! <string name="screen_roomlist_filter_unreads_empty_state_title">"Gefeliciteerd!
Je hebt geen ongelezen berichten!"</string> Je hebt geen ongelezen berichten!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Verzoek om toe te treden verzonden"</string>
<string name="screen_roomlist_main_space_title">"Chats"</string> <string name="screen_roomlist_main_space_title">"Chats"</string>
<string name="screen_roomlist_mark_as_read">"Markeren als gelezen"</string> <string name="screen_roomlist_mark_as_read">"Markeren als gelezen"</string>
<string name="screen_roomlist_mark_as_unread">"Markeren als ongelezen"</string> <string name="screen_roomlist_mark_as_unread">"Markeren als ongelezen"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Odrzuć czat"</string> <string name="screen_invites_decline_direct_chat_title">"Odrzuć czat"</string>
<string name="screen_invites_empty_list">"Brak zaproszeń"</string> <string name="screen_invites_empty_list">"Brak zaproszeń"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) zaprosił Cię"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) zaprosił Cię"</string>
<string name="screen_join_room_knock_sent_title">"Wysłano prośbę o dołączenie"</string>
<string name="screen_migration_message">"Jest to jednorazowy proces, dziękujemy za czekanie."</string> <string name="screen_migration_message">"Jest to jednorazowy proces, dziękujemy za czekanie."</string>
<string name="screen_migration_title">"Konfigurowanie Twojego konta."</string> <string name="screen_migration_title">"Konfigurowanie Twojego konta."</string>
<string name="screen_roomlist_a11y_create_message">"Utwórz nową rozmowę lub pokój"</string> <string name="screen_roomlist_a11y_create_message">"Utwórz nową rozmowę lub pokój"</string>
@ -37,6 +36,7 @@ Na razie możesz wyczyścić filtry, aby zobaczyć pozostałe czaty"</string>
<string name="screen_roomlist_filter_unreads">"Nieprzeczytane"</string> <string name="screen_roomlist_filter_unreads">"Nieprzeczytane"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Gratulacje! <string name="screen_roomlist_filter_unreads_empty_state_title">"Gratulacje!
Nie masz żadnych nieprzeczytanych wiadomości!"</string> Nie masz żadnych nieprzeczytanych wiadomości!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Wysłano prośbę o dołączenie"</string>
<string name="screen_roomlist_main_space_title">"Wszystkie czaty"</string> <string name="screen_roomlist_main_space_title">"Wszystkie czaty"</string>
<string name="screen_roomlist_mark_as_read">"Oznacz jako przeczytane"</string> <string name="screen_roomlist_mark_as_read">"Oznacz jako przeczytane"</string>
<string name="screen_roomlist_mark_as_unread">"Oznacz jako nieprzeczytane"</string> <string name="screen_roomlist_mark_as_unread">"Oznacz jako nieprzeczytane"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Recusar chat"</string> <string name="screen_invites_decline_direct_chat_title">"Recusar chat"</string>
<string name="screen_invites_empty_list">"Sem convites"</string> <string name="screen_invites_empty_list">"Sem convites"</string>
<string name="screen_invites_invited_you">"%1$s(%2$s) convidou você"</string> <string name="screen_invites_invited_you">"%1$s(%2$s) convidou você"</string>
<string name="screen_join_room_knock_sent_title">"Pedido de adesão enviado"</string>
<string name="screen_migration_message">"Este é um processo único, obrigado por esperar."</string> <string name="screen_migration_message">"Este é um processo único, obrigado por esperar."</string>
<string name="screen_migration_title">"Configurando sua conta."</string> <string name="screen_migration_title">"Configurando sua conta."</string>
<string name="screen_roomlist_a11y_create_message">"Criar uma nova conversa ou sala"</string> <string name="screen_roomlist_a11y_create_message">"Criar uma nova conversa ou sala"</string>
@ -37,6 +36,7 @@ Por enquanto, você pode desmarcar os filtros para ver seus outros bate-papos"</
<string name="screen_roomlist_filter_unreads">"Não lidos"</string> <string name="screen_roomlist_filter_unreads">"Não lidos"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Parabéns! <string name="screen_roomlist_filter_unreads_empty_state_title">"Parabéns!
Você não tem nenhuma mensagem não lida!"</string> Você não tem nenhuma mensagem não lida!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Pedido de adesão enviado"</string>
<string name="screen_roomlist_main_space_title">"Conversas"</string> <string name="screen_roomlist_main_space_title">"Conversas"</string>
<string name="screen_roomlist_mark_as_read">"Marcar como lido"</string> <string name="screen_roomlist_mark_as_read">"Marcar como lido"</string>
<string name="screen_roomlist_mark_as_unread">"Marcar como não lido"</string> <string name="screen_roomlist_mark_as_unread">"Marcar como não lido"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Rejeitar conversa"</string> <string name="screen_invites_decline_direct_chat_title">"Rejeitar conversa"</string>
<string name="screen_invites_empty_list">"Sem convites"</string> <string name="screen_invites_empty_list">"Sem convites"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) convidou-te"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) convidou-te"</string>
<string name="screen_join_room_knock_sent_title">"Pedido de adesão enviado"</string>
<string name="screen_migration_message">"Este processo só acontece uma única vez, obrigado por esperares."</string> <string name="screen_migration_message">"Este processo só acontece uma única vez, obrigado por esperares."</string>
<string name="screen_migration_title">"A configurar a tua conta…"</string> <string name="screen_migration_title">"A configurar a tua conta…"</string>
<string name="screen_roomlist_a11y_create_message">"Criar uma nova conversa ou sala"</string> <string name="screen_roomlist_a11y_create_message">"Criar uma nova conversa ou sala"</string>
@ -37,6 +36,7 @@ Por enquanto, podes anular a seleção dos filtros para veres as tuas outras con
<string name="screen_roomlist_filter_unreads">"Por ler"</string> <string name="screen_roomlist_filter_unreads">"Por ler"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Parabéns! <string name="screen_roomlist_filter_unreads_empty_state_title">"Parabéns!
Não tens nenhuma mensagem por ler!"</string> Não tens nenhuma mensagem por ler!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Pedido de adesão enviado"</string>
<string name="screen_roomlist_main_space_title">"Conversas"</string> <string name="screen_roomlist_main_space_title">"Conversas"</string>
<string name="screen_roomlist_mark_as_read">"Marcar como lida"</string> <string name="screen_roomlist_mark_as_read">"Marcar como lida"</string>
<string name="screen_roomlist_mark_as_unread">"Marcar como não lida"</string> <string name="screen_roomlist_mark_as_unread">"Marcar como não lida"</string>

View file

@ -13,7 +13,6 @@
<string name="screen_invites_decline_direct_chat_title">"Refuzați conversația"</string> <string name="screen_invites_decline_direct_chat_title">"Refuzați conversația"</string>
<string name="screen_invites_empty_list">"Nicio invitație"</string> <string name="screen_invites_empty_list">"Nicio invitație"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) v-a invitat."</string> <string name="screen_invites_invited_you">"%1$s (%2$s) v-a invitat."</string>
<string name="screen_join_room_knock_sent_title">"Cererea de alăturare a fost trimisă"</string>
<string name="screen_migration_message">"Acesta este un proces care se desfășoară o singură dată, vă mulțumim pentru așteptare."</string> <string name="screen_migration_message">"Acesta este un proces care se desfășoară o singură dată, vă mulțumim pentru așteptare."</string>
<string name="screen_migration_title">"Contul dumneavoastră se configurează"</string> <string name="screen_migration_title">"Contul dumneavoastră se configurează"</string>
<string name="screen_roomlist_a11y_create_message">"Creați o conversație sau o cameră nouă"</string> <string name="screen_roomlist_a11y_create_message">"Creați o conversație sau o cameră nouă"</string>
@ -35,6 +34,7 @@ Deocamdată, puteți deselecta filtrele pentru a vedea celelalte chat-uri"</stri
<string name="screen_roomlist_filter_unreads">"Necitite"</string> <string name="screen_roomlist_filter_unreads">"Necitite"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Felicitari! <string name="screen_roomlist_filter_unreads_empty_state_title">"Felicitari!
Nu aveți mesaje necitite!"</string> Nu aveți mesaje necitite!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Cererea de alăturare a fost trimisă"</string>
<string name="screen_roomlist_main_space_title">"Toate conversatiile"</string> <string name="screen_roomlist_main_space_title">"Toate conversatiile"</string>
<string name="screen_roomlist_mark_as_read">"Marcați ca citită"</string> <string name="screen_roomlist_mark_as_read">"Marcați ca citită"</string>
<string name="screen_roomlist_mark_as_unread">"Marcați ca necitită"</string> <string name="screen_roomlist_mark_as_unread">"Marcați ca necitită"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Отклонить чат"</string> <string name="screen_invites_decline_direct_chat_title">"Отклонить чат"</string>
<string name="screen_invites_empty_list">"Нет приглашений"</string> <string name="screen_invites_empty_list">"Нет приглашений"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) пригласил вас"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) пригласил вас"</string>
<string name="screen_join_room_knock_sent_title">"Запрос на присоединение отправлен"</string>
<string name="screen_migration_message">"Это одноразовый процесс, спасибо, что подождали."</string> <string name="screen_migration_message">"Это одноразовый процесс, спасибо, что подождали."</string>
<string name="screen_migration_title">"Настройка учетной записи."</string> <string name="screen_migration_title">"Настройка учетной записи."</string>
<string name="screen_roomlist_a11y_create_message">"Создайте новую беседу или комнату"</string> <string name="screen_roomlist_a11y_create_message">"Создайте новую беседу или комнату"</string>
@ -37,6 +36,7 @@
<string name="screen_roomlist_filter_unreads">"Непрочитанные"</string> <string name="screen_roomlist_filter_unreads">"Непрочитанные"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Поздравляем! <string name="screen_roomlist_filter_unreads_empty_state_title">"Поздравляем!
У вас нет непрочитанных сообщений!"</string> У вас нет непрочитанных сообщений!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Запрос на присоединение отправлен"</string>
<string name="screen_roomlist_main_space_title">"Все чаты"</string> <string name="screen_roomlist_main_space_title">"Все чаты"</string>
<string name="screen_roomlist_mark_as_read">"Пометить как прочитанное"</string> <string name="screen_roomlist_mark_as_read">"Пометить как прочитанное"</string>
<string name="screen_roomlist_mark_as_unread">"Отметить как непрочитанное"</string> <string name="screen_roomlist_mark_as_unread">"Отметить как непрочитанное"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Odmietnuť konverzáciu"</string> <string name="screen_invites_decline_direct_chat_title">"Odmietnuť konverzáciu"</string>
<string name="screen_invites_empty_list">"Žiadne pozvánky"</string> <string name="screen_invites_empty_list">"Žiadne pozvánky"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) vás pozval/a"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) vás pozval/a"</string>
<string name="screen_join_room_knock_sent_title">"Žiadosť o pripojenie bola odoslaná"</string>
<string name="screen_migration_message">"Ide o jednorazový proces, ďakujeme za trpezlivosť."</string> <string name="screen_migration_message">"Ide o jednorazový proces, ďakujeme za trpezlivosť."</string>
<string name="screen_migration_title">"Nastavenie vášho účtu."</string> <string name="screen_migration_title">"Nastavenie vášho účtu."</string>
<string name="screen_roomlist_a11y_create_message">"Vytvorte novú konverzáciu alebo miestnosť"</string> <string name="screen_roomlist_a11y_create_message">"Vytvorte novú konverzáciu alebo miestnosť"</string>
@ -37,6 +36,7 @@ Zatiaľ môžete zrušiť výber filtrov, aby ste videli ostatné konverzácie"<
<string name="screen_roomlist_filter_unreads">"Neprečítané"</string> <string name="screen_roomlist_filter_unreads">"Neprečítané"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Gratulujeme! <string name="screen_roomlist_filter_unreads_empty_state_title">"Gratulujeme!
Nemáte žiadne neprečítané správy!"</string> Nemáte žiadne neprečítané správy!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Žiadosť o pripojenie bola odoslaná"</string>
<string name="screen_roomlist_main_space_title">"Všetky konverzácie"</string> <string name="screen_roomlist_main_space_title">"Všetky konverzácie"</string>
<string name="screen_roomlist_mark_as_read">"Označiť ako prečítané"</string> <string name="screen_roomlist_mark_as_read">"Označiť ako prečítané"</string>
<string name="screen_roomlist_mark_as_unread">"Označiť ako neprečítané"</string> <string name="screen_roomlist_mark_as_unread">"Označiť ako neprečítané"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Avböj chatt"</string> <string name="screen_invites_decline_direct_chat_title">"Avböj chatt"</string>
<string name="screen_invites_empty_list">"Inga inbjudningar"</string> <string name="screen_invites_empty_list">"Inga inbjudningar"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) bjöd in dig"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) bjöd in dig"</string>
<string name="screen_join_room_knock_sent_title">"Begäran om att gå med skickad"</string>
<string name="screen_migration_message">"Detta är en engångsprocess, tack för att du väntar."</string> <string name="screen_migration_message">"Detta är en engångsprocess, tack för att du väntar."</string>
<string name="screen_migration_title">"Konfigurerar ditt konto"</string> <string name="screen_migration_title">"Konfigurerar ditt konto"</string>
<string name="screen_roomlist_a11y_create_message">"Skapa en ny konversation eller ett nytt rum"</string> <string name="screen_roomlist_a11y_create_message">"Skapa en ny konversation eller ett nytt rum"</string>
@ -37,6 +36,7 @@ För tillfället kan du avmarkera filter för att se dina andra chattar"</string
<string name="screen_roomlist_filter_unreads">"Olästa"</string> <string name="screen_roomlist_filter_unreads">"Olästa"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Grattis! <string name="screen_roomlist_filter_unreads_empty_state_title">"Grattis!
Du har inga olästa meddelanden!"</string> Du har inga olästa meddelanden!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Begäran om att gå med skickad"</string>
<string name="screen_roomlist_main_space_title">"Alla chattar"</string> <string name="screen_roomlist_main_space_title">"Alla chattar"</string>
<string name="screen_roomlist_mark_as_read">"Markera som läst"</string> <string name="screen_roomlist_mark_as_read">"Markera som läst"</string>
<string name="screen_roomlist_mark_as_unread">"Markera som oläst"</string> <string name="screen_roomlist_mark_as_unread">"Markera som oläst"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Sohbeti reddet"</string> <string name="screen_invites_decline_direct_chat_title">"Sohbeti reddet"</string>
<string name="screen_invites_empty_list">"Davet Yok"</string> <string name="screen_invites_empty_list">"Davet Yok"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) sizi davet etti"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) sizi davet etti"</string>
<string name="screen_join_room_knock_sent_title">"Katılma isteği gönderildi"</string>
<string name="screen_migration_message">"Bu tek seferlik bir işlemdir, beklediğiniz için teşekkürler."</string> <string name="screen_migration_message">"Bu tek seferlik bir işlemdir, beklediğiniz için teşekkürler."</string>
<string name="screen_migration_title">"Hesabınızı ayarlanıyor."</string> <string name="screen_migration_title">"Hesabınızı ayarlanıyor."</string>
<string name="screen_roomlist_a11y_create_message">"Yeni bir sohbet veya oda oluşturun"</string> <string name="screen_roomlist_a11y_create_message">"Yeni bir sohbet veya oda oluşturun"</string>
@ -37,6 +36,7 @@
<string name="screen_roomlist_filter_unreads">"Okunmamış"</string> <string name="screen_roomlist_filter_unreads">"Okunmamış"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Tebrikler! <string name="screen_roomlist_filter_unreads_empty_state_title">"Tebrikler!
Okunmamış mesajınız yok!"</string> Okunmamış mesajınız yok!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Katılma isteği gönderildi"</string>
<string name="screen_roomlist_main_space_title">"Sohbetler"</string> <string name="screen_roomlist_main_space_title">"Sohbetler"</string>
<string name="screen_roomlist_mark_as_read">"Okundu olarak işaretle"</string> <string name="screen_roomlist_mark_as_read">"Okundu olarak işaretle"</string>
<string name="screen_roomlist_mark_as_unread">"Okunmamış olarak işaretle"</string> <string name="screen_roomlist_mark_as_unread">"Okunmamış olarak işaretle"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"Відхилити бесіду"</string> <string name="screen_invites_decline_direct_chat_title">"Відхилити бесіду"</string>
<string name="screen_invites_empty_list">"Немає запрошень"</string> <string name="screen_invites_empty_list">"Немає запрошень"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) запрошує вас"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) запрошує вас"</string>
<string name="screen_join_room_knock_sent_title">"Запит на приєднання надіслано"</string>
<string name="screen_migration_message">"Це одноразовий процес, дякую за очікування."</string> <string name="screen_migration_message">"Це одноразовий процес, дякую за очікування."</string>
<string name="screen_migration_title">"Налаштування облікового запису."</string> <string name="screen_migration_title">"Налаштування облікового запису."</string>
<string name="screen_roomlist_a11y_create_message">"Створити нову розмову або кімнату"</string> <string name="screen_roomlist_a11y_create_message">"Створити нову розмову або кімнату"</string>
@ -37,6 +36,7 @@
<string name="screen_roomlist_filter_unreads">"Непрочитані"</string> <string name="screen_roomlist_filter_unreads">"Непрочитані"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Вітаємо! <string name="screen_roomlist_filter_unreads_empty_state_title">"Вітаємо!
У вас немає непрочитаних повідомлень!"</string> У вас немає непрочитаних повідомлень!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Запит на приєднання надіслано"</string>
<string name="screen_roomlist_main_space_title">"Бесіди"</string> <string name="screen_roomlist_main_space_title">"Бесіди"</string>
<string name="screen_roomlist_mark_as_read">"Позначити прочитаним"</string> <string name="screen_roomlist_mark_as_read">"Позначити прочитаним"</string>
<string name="screen_roomlist_mark_as_unread">"Позначити непрочитаним"</string> <string name="screen_roomlist_mark_as_unread">"Позначити непрочитаним"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"拒絕聊天"</string> <string name="screen_invites_decline_direct_chat_title">"拒絕聊天"</string>
<string name="screen_invites_empty_list">"沒有邀請"</string> <string name="screen_invites_empty_list">"沒有邀請"</string>
<string name="screen_invites_invited_you">"%1$s%2$s邀請您"</string> <string name="screen_invites_invited_you">"%1$s%2$s邀請您"</string>
<string name="screen_join_room_knock_sent_title">"已傳送加入請求"</string>
<string name="screen_migration_message">"這是一次性的程序,感謝您耐心等候。"</string> <string name="screen_migration_message">"這是一次性的程序,感謝您耐心等候。"</string>
<string name="screen_migration_title">"正在設定您的帳號。"</string> <string name="screen_migration_title">"正在設定您的帳號。"</string>
<string name="screen_roomlist_a11y_create_message">"建立新的對話或聊天室"</string> <string name="screen_roomlist_a11y_create_message">"建立新的對話或聊天室"</string>
@ -37,6 +36,7 @@
<string name="screen_roomlist_filter_unreads">"未讀"</string> <string name="screen_roomlist_filter_unreads">"未讀"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"恭喜! <string name="screen_roomlist_filter_unreads_empty_state_title">"恭喜!
您沒有任何未讀的訊息!"</string> 您沒有任何未讀的訊息!"</string>
<string name="screen_roomlist_knock_event_sent_description">"已傳送加入請求"</string>
<string name="screen_roomlist_main_space_title">"所有聊天室"</string> <string name="screen_roomlist_main_space_title">"所有聊天室"</string>
<string name="screen_roomlist_mark_as_read">"標為已讀"</string> <string name="screen_roomlist_mark_as_read">"標為已讀"</string>
<string name="screen_roomlist_mark_as_unread">"標為未讀"</string> <string name="screen_roomlist_mark_as_unread">"標為未讀"</string>

View file

@ -15,7 +15,6 @@
<string name="screen_invites_decline_direct_chat_title">"拒绝聊天"</string> <string name="screen_invites_decline_direct_chat_title">"拒绝聊天"</string>
<string name="screen_invites_empty_list">"没有邀请"</string> <string name="screen_invites_empty_list">"没有邀请"</string>
<string name="screen_invites_invited_you">"%1$s %2$s邀请了你"</string> <string name="screen_invites_invited_you">"%1$s %2$s邀请了你"</string>
<string name="screen_join_room_knock_sent_title">"加入请求已发送"</string>
<string name="screen_migration_message">"这是一个一次性的过程,感谢您的等待。"</string> <string name="screen_migration_message">"这是一个一次性的过程,感谢您的等待。"</string>
<string name="screen_migration_title">"设置您的账户。"</string> <string name="screen_migration_title">"设置您的账户。"</string>
<string name="screen_roomlist_a11y_create_message">"创建新的对话或聊天室"</string> <string name="screen_roomlist_a11y_create_message">"创建新的对话或聊天室"</string>
@ -37,6 +36,7 @@
<string name="screen_roomlist_filter_unreads">"未读"</string> <string name="screen_roomlist_filter_unreads">"未读"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"恭喜! <string name="screen_roomlist_filter_unreads_empty_state_title">"恭喜!
没有任何未读消息!"</string> 没有任何未读消息!"</string>
<string name="screen_roomlist_knock_event_sent_description">"加入请求已发送"</string>
<string name="screen_roomlist_main_space_title">"全部聊天"</string> <string name="screen_roomlist_main_space_title">"全部聊天"</string>
<string name="screen_roomlist_mark_as_read">"标记为已读"</string> <string name="screen_roomlist_mark_as_read">"标记为已读"</string>
<string name="screen_roomlist_mark_as_unread">"标记为未读"</string> <string name="screen_roomlist_mark_as_unread">"标记为未读"</string>

View file

@ -18,7 +18,6 @@
<string name="screen_invites_decline_direct_chat_title">"Decline chat"</string> <string name="screen_invites_decline_direct_chat_title">"Decline chat"</string>
<string name="screen_invites_empty_list">"No Invites"</string> <string name="screen_invites_empty_list">"No Invites"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) invited you"</string> <string name="screen_invites_invited_you">"%1$s (%2$s) invited you"</string>
<string name="screen_join_room_knock_sent_title">"Request to join sent"</string>
<string name="screen_migration_message">"This is a one time process, thanks for waiting."</string> <string name="screen_migration_message">"This is a one time process, thanks for waiting."</string>
<string name="screen_migration_title">"Setting up your account."</string> <string name="screen_migration_title">"Setting up your account."</string>
<string name="screen_roomlist_a11y_create_message">"Create a new conversation or room"</string> <string name="screen_roomlist_a11y_create_message">"Create a new conversation or room"</string>
@ -40,9 +39,11 @@ For now, you can deselect filters in order to see your other chats"</string>
<string name="screen_roomlist_filter_unreads">"Unreads"</string> <string name="screen_roomlist_filter_unreads">"Unreads"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Congrats! <string name="screen_roomlist_filter_unreads_empty_state_title">"Congrats!
You dont have any unread messages!"</string> You dont have any unread messages!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Request to join sent"</string>
<string name="screen_roomlist_main_space_title">"Chats"</string> <string name="screen_roomlist_main_space_title">"Chats"</string>
<string name="screen_roomlist_mark_as_read">"Mark as read"</string> <string name="screen_roomlist_mark_as_read">"Mark as read"</string>
<string name="screen_roomlist_mark_as_unread">"Mark as unread"</string> <string name="screen_roomlist_mark_as_unread">"Mark as unread"</string>
<string name="screen_roomlist_tombstoned_room_description">"This room has been upgraded"</string>
<string name="session_verification_banner_message">"Looks like youre using a new device. Verify with another device to access your encrypted messages."</string> <string name="session_verification_banner_message">"Looks like youre using a new device. Verify with another device to access your encrypted messages."</string>
<string name="session_verification_banner_title">"Verify its you"</string> <string name="session_verification_banner_title">"Verify its you"</string>
</resources> </resources>

View file

@ -39,7 +39,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
fun ComposerAlertMolecule( fun ComposerAlertMolecule(
avatar: AvatarData, avatar: AvatarData?,
content: AnnotatedString, content: AnnotatedString,
onSubmitClick: () -> Unit, onSubmitClick: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -71,9 +71,9 @@ fun ComposerAlertMolecule(
Row( Row(
horizontalArrangement = Arrangement.spacedBy(16.dp) horizontalArrangement = Arrangement.spacedBy(16.dp)
) { ) {
Avatar( if (avatar != null) {
avatarData = avatar, Avatar(avatarData = avatar)
) }
Text( Text(
text = content, text = content,
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),

View file

@ -13,6 +13,7 @@ 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.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels
import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.ReceiptType
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -55,6 +56,8 @@ interface BaseRoom : Closeable {
*/ */
fun info(): RoomInfo = roomInfoFlow.value fun info(): RoomInfo = roomInfoFlow.value
fun predecessorRoom(): PredecessorRoom?
/** /**
* A one-to-one is a room with exactly 2 members. * A one-to-one is a room with exactly 2 members.
* See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/#default-underride-rules). * See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/#default-underride-rules).

View file

@ -14,6 +14,7 @@ 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.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 kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.ImmutableMap

View file

@ -0,0 +1,31 @@
/*
* Copyright 2025 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.room.tombstone
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId
/**
*
* When a room A is tombstoned, it is replaced by a room B. The room A is the
* predecessor of B, and B is the successor of A. This type holds information
* about the predecessor room.
*
* A room is tombstoned if it has received a m.room.tombstone state event.
*
*/
data class PredecessorRoom(
/**
* The ID of the replaced room.
*/
val roomId: RoomId,
/**
* The event ID of the last known event in the predecessor room.
*/
val lastEventId: EventId,
)

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.matrix.api.room package io.element.android.libraries.matrix.api.room.tombstone
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId

View file

@ -14,11 +14,11 @@ 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.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
import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
import io.element.android.libraries.matrix.impl.room.tombstone.map
import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentMap import kotlinx.collections.immutable.toPersistentMap
@ -28,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 {
@ -88,11 +87,6 @@ fun RustRoomNotificationMode.map(): RoomNotificationMode = when (this) {
RustRoomNotificationMode.MUTE -> RoomNotificationMode.MUTE RustRoomNotificationMode.MUTE -> RoomNotificationMode.MUTE
} }
fun RustSuccessorRoom.map(): SuccessorRoom = SuccessorRoom(
roomId = RoomId(roomId),
reason = reason,
)
/** /**
* Map a RoomHero to a MatrixUser. There is not need to create a RoomHero type on the application side. * Map a RoomHero to a MatrixUser. There is not need to create a RoomHero type on the application side.
*/ */

View file

@ -24,12 +24,14 @@ import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels
import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.matrix.impl.room.draft.into import io.element.android.libraries.matrix.impl.room.draft.into
import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher
import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
import io.element.android.libraries.matrix.impl.room.powerlevels.RoomPowerLevelsMapper import io.element.android.libraries.matrix.impl.room.powerlevels.RoomPowerLevelsMapper
import io.element.android.libraries.matrix.impl.room.tombstone.map
import io.element.android.libraries.matrix.impl.roomdirectory.map import io.element.android.libraries.matrix.impl.roomdirectory.map
import io.element.android.libraries.matrix.impl.timeline.toRustReceiptType import io.element.android.libraries.matrix.impl.timeline.toRustReceiptType
import io.element.android.libraries.matrix.impl.util.mxCallbackFlow import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
@ -78,6 +80,10 @@ class RustBaseRoom(
}) })
}.stateIn(roomCoroutineScope, started = SharingStarted.Lazily, initialValue = initialRoomInfo) }.stateIn(roomCoroutineScope, started = SharingStarted.Lazily, initialValue = initialRoomInfo)
override fun predecessorRoom(): PredecessorRoom? {
return innerRoom.predecessorRoom()?.map()
}
override suspend fun subscribeToSync() = roomSyncSubscriber.subscribe(roomId) override suspend fun subscribeToSync() = roomSyncSubscriber.subscribe(roomId)
override suspend fun updateMembers() { override suspend fun updateMembers() {

View file

@ -0,0 +1,20 @@
/*
* Copyright 2025 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.impl.room.tombstone
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.room.tombstone.PredecessorRoom
import org.matrix.rustcomponents.sdk.PredecessorRoom as RustPredecessorRoom
fun RustPredecessorRoom.map(): PredecessorRoom {
return PredecessorRoom(
roomId = RoomId(roomId),
lastEventId = EventId(lastEventId),
)
}

View file

@ -0,0 +1,19 @@
/*
* Copyright 2025 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.impl.room.tombstone
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
import org.matrix.rustcomponents.sdk.SuccessorRoom as RustSuccessorRoom
fun RustSuccessorRoom.map(): SuccessorRoom {
return SuccessorRoom(
roomId = RoomId(roomId),
reason = reason
)
}

View file

@ -27,6 +27,11 @@ import org.matrix.rustcomponents.sdk.RoomListService
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import org.matrix.rustcomponents.sdk.RoomList as InnerRoomList import org.matrix.rustcomponents.sdk.RoomList as InnerRoomList
private val ROOM_LIST_RUST_FILTERS = listOf(
RoomListEntriesDynamicFilterKind.NonLeft,
RoomListEntriesDynamicFilterKind.DeduplicateVersions
)
internal class RoomListFactory( internal class RoomListFactory(
private val innerRoomListService: RoomListService, private val innerRoomListService: RoomListService,
private val sessionCoroutineScope: CoroutineScope, private val sessionCoroutineScope: CoroutineScope,
@ -55,11 +60,11 @@ internal class RoomListFactory(
coroutineScope.launch(coroutineContext) { coroutineScope.launch(coroutineContext) {
innerRoomList = innerProvider() innerRoomList = innerProvider()
innerRoomList?.let { innerRoomList -> innerRoomList.let { innerRoomList ->
innerRoomList.entriesFlow( innerRoomList.entriesFlow(
pageSize = pageSize, pageSize = pageSize,
roomListDynamicEvents = dynamicEvents, roomListDynamicEvents = dynamicEvents,
initialFilterKind = RoomListEntriesDynamicFilterKind.NonLeft initialFilterKind = RoomListEntriesDynamicFilterKind.All(ROOM_LIST_RUST_FILTERS),
).onEach { update -> ).onEach { update ->
processor.postUpdate(update) processor.postUpdate(update)
}.launchIn(this) }.launchIn(this)

View file

@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels
import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID
@ -66,6 +67,7 @@ class FakeBaseRoom(
private val getRoomVisibilityResult: () -> Result<RoomVisibility> = { lambdaError() }, private val getRoomVisibilityResult: () -> Result<RoomVisibility> = { lambdaError() },
private val forgetResult: () -> Result<Unit> = { lambdaError() }, private val forgetResult: () -> Result<Unit> = { lambdaError() },
private val reportRoomResult: (String?) -> Result<Unit> = { lambdaError() }, private val reportRoomResult: (String?) -> Result<Unit> = { lambdaError() },
private val predecessorRoomResult: () -> PredecessorRoom? = { null },
) : BaseRoom { ) : BaseRoom {
private val _roomInfoFlow: MutableStateFlow<RoomInfo> = MutableStateFlow(initialRoomInfo) private val _roomInfoFlow: MutableStateFlow<RoomInfo> = MutableStateFlow(initialRoomInfo)
override val roomInfoFlow: StateFlow<RoomInfo> = _roomInfoFlow override val roomInfoFlow: StateFlow<RoomInfo> = _roomInfoFlow
@ -215,6 +217,8 @@ class FakeBaseRoom(
} }
override suspend fun reportRoom(reason: String?) = reportRoomResult(reason) override suspend fun reportRoom(reason: String?) = reportRoomResult(reason)
override fun predecessorRoom(): PredecessorRoom? = predecessorRoomResult()
} }
fun defaultRoomPowerLevels() = RoomPowerLevels( fun defaultRoomPowerLevels() = RoomPowerLevels(

View file

@ -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.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

View file

@ -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.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

View file

@ -396,7 +396,6 @@ Ydych chi\'n siŵr eich bod am barhau?"</string>
<string name="screen_room_pinned_banner_loading_description">"Wrthi\'n llwytho neges…"</string> <string name="screen_room_pinned_banner_loading_description">"Wrthi\'n llwytho neges…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Dangos y Cyfan"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Dangos y Cyfan"</string>
<string name="screen_room_title">"Sgwrs"</string> <string name="screen_room_title">"Sgwrs"</string>
<string name="screen_roomlist_knock_event_sent_description">"Anfonwyd y cais i ymuno"</string>
<string name="screen_share_location_title">"Rhannu lleoliad"</string> <string name="screen_share_location_title">"Rhannu lleoliad"</string>
<string name="screen_share_my_location_action">"Rhannu fy lleoliad"</string> <string name="screen_share_my_location_action">"Rhannu fy lleoliad"</string>
<string name="screen_share_open_apple_maps">"Agor yn Apple Maps"</string> <string name="screen_share_open_apple_maps">"Agor yn Apple Maps"</string>

View file

@ -372,7 +372,6 @@ Möchten Sie wirklich fortfahren?"</string>
<string name="screen_room_pinned_banner_loading_description">"Nachricht wird geladen…"</string> <string name="screen_room_pinned_banner_loading_description">"Nachricht wird geladen…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Alle anzeigen"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Alle anzeigen"</string>
<string name="screen_room_title">"Chat"</string> <string name="screen_room_title">"Chat"</string>
<string name="screen_roomlist_knock_event_sent_description">"Beitrittsanfrage geschickt"</string>
<string name="screen_share_location_title">"Standort teilen"</string> <string name="screen_share_location_title">"Standort teilen"</string>
<string name="screen_share_my_location_action">"Meinen Standort teilen"</string> <string name="screen_share_my_location_action">"Meinen Standort teilen"</string>
<string name="screen_share_open_apple_maps">"In Apple Maps öffnen"</string> <string name="screen_share_open_apple_maps">"In Apple Maps öffnen"</string>

View file

@ -372,7 +372,6 @@
<string name="screen_room_pinned_banner_loading_description">"Φόρτωση μηνύματος…"</string> <string name="screen_room_pinned_banner_loading_description">"Φόρτωση μηνύματος…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Προβολή Όλων"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Προβολή Όλων"</string>
<string name="screen_room_title">"Συνομιλία"</string> <string name="screen_room_title">"Συνομιλία"</string>
<string name="screen_roomlist_knock_event_sent_description">"Το αίτημα συμμετοχής στάλθηκε"</string>
<string name="screen_share_location_title">"Κοινή χρήση τοποθεσίας"</string> <string name="screen_share_location_title">"Κοινή χρήση τοποθεσίας"</string>
<string name="screen_share_my_location_action">"Κοινή χρήση της τοποθεσίας μου"</string> <string name="screen_share_my_location_action">"Κοινή χρήση της τοποθεσίας μου"</string>
<string name="screen_share_open_apple_maps">"Άνοιγμα στο Apple Maps"</string> <string name="screen_share_open_apple_maps">"Άνοιγμα στο Apple Maps"</string>

View file

@ -372,7 +372,6 @@ Motivo: %1$s."</string>
<string name="screen_room_pinned_banner_loading_description">"Cargando mensaje…"</string> <string name="screen_room_pinned_banner_loading_description">"Cargando mensaje…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Ver todos"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Ver todos"</string>
<string name="screen_room_title">"Chat"</string> <string name="screen_room_title">"Chat"</string>
<string name="screen_roomlist_knock_event_sent_description">"Solicitud de unión enviada"</string>
<string name="screen_share_location_title">"Compartir ubicación"</string> <string name="screen_share_location_title">"Compartir ubicación"</string>
<string name="screen_share_my_location_action">"Compartir mi ubicación"</string> <string name="screen_share_my_location_action">"Compartir mi ubicación"</string>
<string name="screen_share_open_apple_maps">"Abrir en Apple Maps"</string> <string name="screen_share_open_apple_maps">"Abrir en Apple Maps"</string>

View file

@ -330,7 +330,6 @@ Arrazoia: %1$s."</string>
<string name="screen_room_pinned_banner_loading_description">"Mezua kargatzen…"</string> <string name="screen_room_pinned_banner_loading_description">"Mezua kargatzen…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Ikusi guztia"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Ikusi guztia"</string>
<string name="screen_room_title">"Txata"</string> <string name="screen_room_title">"Txata"</string>
<string name="screen_roomlist_knock_event_sent_description">"Sartzeko eskaera bidali da"</string>
<string name="screen_share_location_title">"Partekatu kokapena"</string> <string name="screen_share_location_title">"Partekatu kokapena"</string>
<string name="screen_share_my_location_action">"Partekatu nire kokapena"</string> <string name="screen_share_my_location_action">"Partekatu nire kokapena"</string>
<string name="screen_share_open_apple_maps">"Ireki Apple Maps-en"</string> <string name="screen_share_open_apple_maps">"Ireki Apple Maps-en"</string>

View file

@ -323,7 +323,6 @@
<string name="screen_room_pinned_banner_loading_description">"بار کردن پشام‌ها…"</string> <string name="screen_room_pinned_banner_loading_description">"بار کردن پشام‌ها…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"نمایش همه"</string> <string name="screen_room_pinned_banner_view_all_button_title">"نمایش همه"</string>
<string name="screen_room_title">"گپ"</string> <string name="screen_room_title">"گپ"</string>
<string name="screen_roomlist_knock_event_sent_description">"درخواست پیوستن فرستاده شد"</string>
<string name="screen_share_location_title">"هم‌رسانی موقعیت"</string> <string name="screen_share_location_title">"هم‌رسانی موقعیت"</string>
<string name="screen_share_my_location_action">"هم‌رسانی مکانم"</string> <string name="screen_share_my_location_action">"هم‌رسانی مکانم"</string>
<string name="screen_share_open_apple_maps">"گشودن در نقشه‌های اپل"</string> <string name="screen_share_open_apple_maps">"گشودن در نقشه‌های اپل"</string>

View file

@ -334,7 +334,6 @@ Alasan: %1$s."</string>
<string name="screen_room_pinned_banner_loading_description">"Memuat pesan…"</string> <string name="screen_room_pinned_banner_loading_description">"Memuat pesan…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Lihat Semua"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Lihat Semua"</string>
<string name="screen_room_title">"Obrolan"</string> <string name="screen_room_title">"Obrolan"</string>
<string name="screen_roomlist_knock_event_sent_description">"Permintaan untuk bergabung dikirim"</string>
<string name="screen_share_location_title">"Bagikan lokasi"</string> <string name="screen_share_location_title">"Bagikan lokasi"</string>
<string name="screen_share_my_location_action">"Bagikan lokasi saya"</string> <string name="screen_share_my_location_action">"Bagikan lokasi saya"</string>
<string name="screen_share_open_apple_maps">"Buka di Apple Maps"</string> <string name="screen_share_open_apple_maps">"Buka di Apple Maps"</string>

View file

@ -359,7 +359,6 @@ Sei sicuro di voler continuare?"</string>
<string name="screen_room_pinned_banner_loading_description">"Caricamento messaggio…"</string> <string name="screen_room_pinned_banner_loading_description">"Caricamento messaggio…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Mostra tutti"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Mostra tutti"</string>
<string name="screen_room_title">"Conversazione"</string> <string name="screen_room_title">"Conversazione"</string>
<string name="screen_roomlist_knock_event_sent_description">"Richiesta di accesso inviata"</string>
<string name="screen_share_location_title">"Condividi posizione"</string> <string name="screen_share_location_title">"Condividi posizione"</string>
<string name="screen_share_my_location_action">"Condividi la mia posizione"</string> <string name="screen_share_my_location_action">"Condividi la mia posizione"</string>
<string name="screen_share_open_apple_maps">"Apri in Apple Maps"</string> <string name="screen_share_open_apple_maps">"Apri in Apple Maps"</string>

View file

@ -323,7 +323,6 @@ Reden: %1$s."</string>
<string name="screen_room_pinned_banner_loading_description">"Bericht laden…"</string> <string name="screen_room_pinned_banner_loading_description">"Bericht laden…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Bekijk alles"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Bekijk alles"</string>
<string name="screen_room_title">"Chat"</string> <string name="screen_room_title">"Chat"</string>
<string name="screen_roomlist_knock_event_sent_description">"Verzoek om toe te treden verzonden"</string>
<string name="screen_share_location_title">"Locatie delen"</string> <string name="screen_share_location_title">"Locatie delen"</string>
<string name="screen_share_my_location_action">"Deel mijn locatie"</string> <string name="screen_share_my_location_action">"Deel mijn locatie"</string>
<string name="screen_share_open_apple_maps">"Openen in Apple Maps"</string> <string name="screen_share_open_apple_maps">"Openen in Apple Maps"</string>

View file

@ -378,7 +378,6 @@ Czy na pewno chcesz kontynuować?"</string>
<string name="screen_room_pinned_banner_loading_description">"Wczytywanie wiadomości…"</string> <string name="screen_room_pinned_banner_loading_description">"Wczytywanie wiadomości…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Wyświetl wszystkie"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Wyświetl wszystkie"</string>
<string name="screen_room_title">"Czat"</string> <string name="screen_room_title">"Czat"</string>
<string name="screen_roomlist_knock_event_sent_description">"Wysłano prośbę o dołączenie"</string>
<string name="screen_share_location_title">"Udostępnij lokalizację"</string> <string name="screen_share_location_title">"Udostępnij lokalizację"</string>
<string name="screen_share_my_location_action">"Udostępnij moją lokalizację"</string> <string name="screen_share_my_location_action">"Udostępnij moją lokalizację"</string>
<string name="screen_share_open_apple_maps">"Otwórz w Apple Maps"</string> <string name="screen_share_open_apple_maps">"Otwórz w Apple Maps"</string>

View file

@ -372,7 +372,6 @@ Você tem certeza de que deseja continuar?"</string>
<string name="screen_room_pinned_banner_loading_description">"Carregando mensagem…"</string> <string name="screen_room_pinned_banner_loading_description">"Carregando mensagem…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Ver tudo"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Ver tudo"</string>
<string name="screen_room_title">"Bate-papo"</string> <string name="screen_room_title">"Bate-papo"</string>
<string name="screen_roomlist_knock_event_sent_description">"Pedido de adesão enviado"</string>
<string name="screen_share_location_title">"Compartilhar localização"</string> <string name="screen_share_location_title">"Compartilhar localização"</string>
<string name="screen_share_my_location_action">"Compartilhar minha localização"</string> <string name="screen_share_my_location_action">"Compartilhar minha localização"</string>
<string name="screen_share_open_apple_maps">"Abrir no Apple Maps"</string> <string name="screen_share_open_apple_maps">"Abrir no Apple Maps"</string>

View file

@ -372,7 +372,6 @@ Tens a certeza de que queres continuar?"</string>
<string name="screen_room_pinned_banner_loading_description">"A carregar mensagem…"</string> <string name="screen_room_pinned_banner_loading_description">"A carregar mensagem…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Ver todas"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Ver todas"</string>
<string name="screen_room_title">"Conversa"</string> <string name="screen_room_title">"Conversa"</string>
<string name="screen_roomlist_knock_event_sent_description">"Pedido de adesão enviado"</string>
<string name="screen_share_location_title">"Partilhar localização"</string> <string name="screen_share_location_title">"Partilhar localização"</string>
<string name="screen_share_my_location_action">"Partilhar a minha localização"</string> <string name="screen_share_my_location_action">"Partilhar a minha localização"</string>
<string name="screen_share_open_apple_maps">"Abrir no Apple Maps"</string> <string name="screen_share_open_apple_maps">"Abrir no Apple Maps"</string>

View file

@ -327,7 +327,6 @@ Motiv:%1$s."</string>
<string name="screen_room_pinned_banner_loading_description">"Se încarcă mesajul…"</string> <string name="screen_room_pinned_banner_loading_description">"Se încarcă mesajul…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Vedeți toate"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Vedeți toate"</string>
<string name="screen_room_title">"Chat"</string> <string name="screen_room_title">"Chat"</string>
<string name="screen_roomlist_knock_event_sent_description">"Cererea de alăturare a fost trimisă"</string>
<string name="screen_share_location_title">"Partajați locația"</string> <string name="screen_share_location_title">"Partajați locația"</string>
<string name="screen_share_my_location_action">"Distribuiți locația mea"</string> <string name="screen_share_my_location_action">"Distribuiți locația mea"</string>
<string name="screen_share_open_apple_maps">"Deschideți în Apple Maps"</string> <string name="screen_share_open_apple_maps">"Deschideți în Apple Maps"</string>

View file

@ -378,7 +378,6 @@ Naozaj chcete pokračovať?"</string>
<string name="screen_room_pinned_banner_loading_description">"Načítava sa správa…"</string> <string name="screen_room_pinned_banner_loading_description">"Načítava sa správa…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Zobraziť všetko"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Zobraziť všetko"</string>
<string name="screen_room_title">"Konverzácia"</string> <string name="screen_room_title">"Konverzácia"</string>
<string name="screen_roomlist_knock_event_sent_description">"Žiadosť o pripojenie bola odoslaná"</string>
<string name="screen_share_location_title">"Zdieľať polohu"</string> <string name="screen_share_location_title">"Zdieľať polohu"</string>
<string name="screen_share_my_location_action">"Zdieľať moju polohu"</string> <string name="screen_share_my_location_action">"Zdieľať moju polohu"</string>
<string name="screen_share_open_apple_maps">"Otvoriť v Apple Maps"</string> <string name="screen_share_open_apple_maps">"Otvoriť v Apple Maps"</string>

View file

@ -348,7 +348,6 @@ Neden: %1$s."</string>
<string name="screen_room_pinned_banner_loading_description">"Mesaj yükleniyor…"</string> <string name="screen_room_pinned_banner_loading_description">"Mesaj yükleniyor…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Tümünü görüntüle"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Tümünü görüntüle"</string>
<string name="screen_room_title">"Sohbet"</string> <string name="screen_room_title">"Sohbet"</string>
<string name="screen_roomlist_knock_event_sent_description">"Katılma isteği gönderildi"</string>
<string name="screen_share_location_title">"Konum paylaş"</string> <string name="screen_share_location_title">"Konum paylaş"</string>
<string name="screen_share_my_location_action">"Konumumu paylaş"</string> <string name="screen_share_my_location_action">"Konumumu paylaş"</string>
<string name="screen_share_open_apple_maps">"Apple Maps\'de aç"</string> <string name="screen_share_open_apple_maps">"Apple Maps\'de aç"</string>

View file

@ -378,7 +378,6 @@
<string name="screen_room_pinned_banner_loading_description">"Завантаження повідомлення…"</string> <string name="screen_room_pinned_banner_loading_description">"Завантаження повідомлення…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"Переглянути всі"</string> <string name="screen_room_pinned_banner_view_all_button_title">"Переглянути всі"</string>
<string name="screen_room_title">"Бесіда"</string> <string name="screen_room_title">"Бесіда"</string>
<string name="screen_roomlist_knock_event_sent_description">"Запит на приєднання надіслано"</string>
<string name="screen_share_location_title">"Поділитися розташуванням"</string> <string name="screen_share_location_title">"Поділитися розташуванням"</string>
<string name="screen_share_my_location_action">"Поділитися моїм розташуванням"</string> <string name="screen_share_my_location_action">"Поділитися моїм розташуванням"</string>
<string name="screen_share_open_apple_maps">"Відкрити в Apple Maps"</string> <string name="screen_share_open_apple_maps">"Відкрити в Apple Maps"</string>

View file

@ -366,7 +366,6 @@
<string name="screen_room_pinned_banner_loading_description">"正在載入訊息……"</string> <string name="screen_room_pinned_banner_loading_description">"正在載入訊息……"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"檢視全部"</string> <string name="screen_room_pinned_banner_view_all_button_title">"檢視全部"</string>
<string name="screen_room_title">"聊天"</string> <string name="screen_room_title">"聊天"</string>
<string name="screen_roomlist_knock_event_sent_description">"已傳送加入請求"</string>
<string name="screen_share_location_title">"分享位置"</string> <string name="screen_share_location_title">"分享位置"</string>
<string name="screen_share_my_location_action">"分享我的位置"</string> <string name="screen_share_my_location_action">"分享我的位置"</string>
<string name="screen_share_open_apple_maps">"在 Apple Maps 中開啟"</string> <string name="screen_share_open_apple_maps">"在 Apple Maps 中開啟"</string>

View file

@ -357,7 +357,6 @@
<string name="screen_room_pinned_banner_loading_description">"正在加载消息…"</string> <string name="screen_room_pinned_banner_loading_description">"正在加载消息…"</string>
<string name="screen_room_pinned_banner_view_all_button_title">"查看全部"</string> <string name="screen_room_pinned_banner_view_all_button_title">"查看全部"</string>
<string name="screen_room_title">"聊天"</string> <string name="screen_room_title">"聊天"</string>
<string name="screen_roomlist_knock_event_sent_description">"加入请求已发送"</string>
<string name="screen_share_location_title">"分享位置"</string> <string name="screen_share_location_title">"分享位置"</string>
<string name="screen_share_my_location_action">"分享我的位置"</string> <string name="screen_share_my_location_action">"分享我的位置"</string>
<string name="screen_share_open_apple_maps">"在 Apple Maps 中打开"</string> <string name="screen_share_open_apple_maps">"在 Apple Maps 中打开"</string>

View file

@ -381,6 +381,7 @@ Are you sure you want to continue?"</string>
<string name="screen_room_error_failed_processing_media">"Failed processing media to upload, please try again."</string> <string name="screen_room_error_failed_processing_media">"Failed processing media to upload, please try again."</string>
<string name="screen_room_error_failed_retrieving_user_details">"Could not retrieve user details"</string> <string name="screen_room_error_failed_retrieving_user_details">"Could not retrieve user details"</string>
<string name="screen_room_event_pill">"Message in %1$s"</string> <string name="screen_room_event_pill">"Message in %1$s"</string>
<string name="screen_room_permalink_same_room_android">"Already viewing this room!"</string>
<string name="screen_room_pinned_banner_indicator">"%1$s of %2$s"</string> <string name="screen_room_pinned_banner_indicator">"%1$s of %2$s"</string>
<string name="screen_room_pinned_banner_indicator_description">"%1$s Pinned messages"</string> <string name="screen_room_pinned_banner_indicator_description">"%1$s Pinned messages"</string>
<string name="screen_room_pinned_banner_loading_description">"Loading message…"</string> <string name="screen_room_pinned_banner_loading_description">"Loading message…"</string>

View file

@ -16,6 +16,7 @@ import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.onFirst import androidx.compose.ui.test.onFirst
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performClick
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import org.junit.rules.TestRule import org.junit.rules.TestRule
@ -54,3 +55,8 @@ fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.pressBackKey() {
fun SemanticsNodeInteractionsProvider.pressTag(tag: String) { fun SemanticsNodeInteractionsProvider.pressTag(tag: String) {
onNode(hasTestTag(tag)).performClick() onNode(hasTestTag(tag)).performClick()
} }
fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.assertNoNodeWithText(@StringRes res: Int) {
val text = activity.getString(res)
onNodeWithText(text).assertDoesNotExist()
}

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:138be910fa88b2e59882b909f5d83824503d88676d23d327c1f4948121cbebe0 oid sha256:abf66dd56be501e27477d83f97eed4c948fdf049130d46dc5a23e46e4cf18dfc
size 14297 size 33561

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:4b9ce5853af7f03ac91da6bb318bd4f033936279d211e87efff4ef6ec8794f51 oid sha256:603ce16c8ce5e92c6cf1b2639be69e0dc64b99c1c7f1879762661258d222fd84
size 13988 size 36317

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:79e6ab4ac13eeb03cb02843a122b519a6410aeaad40e5f272d0b09f2547af6e7
size 62973

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3241f342c62665d1a343d085ec9174e0e6555219ce51e74f4199bea74f641183
size 65429

View file

@ -165,14 +165,14 @@
"name" : ":features:roomlist:impl", "name" : ":features:roomlist:impl",
"includeRegex" : [ "includeRegex" : [
"screen_roomlist_.*", "screen_roomlist_.*",
"screen\\.roomlist\\..*",
"session_verification_banner_.*", "session_verification_banner_.*",
"confirm_recovery_key_banner_.*", "confirm_recovery_key_banner_.*",
"banner\\.set_up_recovery\\..*", "banner\\.set_up_recovery\\..*",
"banner\\.battery_optimization\\..*", "banner\\.battery_optimization\\..*",
"full_screen_intent_banner_.*", "full_screen_intent_banner_.*",
"screen_migration_.*", "screen_migration_.*",
"screen_invites_.*", "screen_invites_.*"
"screen\\.join_room\\.knock_sent_title"
] ]
}, },
{ {
@ -211,6 +211,7 @@
"screen_room_message.*", "screen_room_message.*",
"screen_room_retry.*", "screen_room_retry.*",
"screen_room_timeline.*", "screen_room_timeline.*",
"screen\\.room_timeline.*",
"screen_room_typing.*" "screen_room_typing.*"
] ]
}, },