Skip to content

Commit 516c3cf

Browse files
authored
Provide calculated server names when opening a room from another (#5155)
* Provide calculated server names when opening a room from another, based on the most frequently used domain names in the user ids for the users in the room. This helps when following permalinks or navigating to the successor room of a tombstoned one. Previously, the `/summary` endpoint was failing because no server names were used in the `via` parameters.
1 parent 1a31e49 commit 516c3cf

File tree

16 files changed

+54
-27
lines changed

16 files changed

+54
-27
lines changed

appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,8 @@ class LoggedInFlowNode @AssistedInject constructor(
335335
}
336336
is NavTarget.Room -> {
337337
val callback = object : JoinedRoomLoadedFlowNode.Callback {
338-
override fun onOpenRoom(roomId: RoomId) {
339-
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias()))
338+
override fun onOpenRoom(roomId: RoomId, serverNames: List<String>) {
339+
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias(), serverNames))
340340
}
341341

342342
override fun onForwardedToSingleRoom(roomId: RoomId) {

appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class JoinedRoomLoadedFlowNode @AssistedInject constructor(
6969
plugins = plugins,
7070
), DaggerComponentOwner {
7171
interface Callback : Plugin {
72-
fun onOpenRoom(roomId: RoomId)
72+
fun onOpenRoom(roomId: RoomId, serverNames: List<String>)
7373
fun onPermalinkClick(data: PermalinkData, pushToBackstack: Boolean)
7474
fun onForwardedToSingleRoom(roomId: RoomId)
7575
fun onOpenGlobalNotificationSettings()
@@ -121,8 +121,8 @@ class JoinedRoomLoadedFlowNode @AssistedInject constructor(
121121
callbacks.forEach { it.onOpenGlobalNotificationSettings() }
122122
}
123123

124-
override fun onOpenRoom(roomId: RoomId) {
125-
callbacks.forEach { it.onOpenRoom(roomId) }
124+
override fun onOpenRoom(roomId: RoomId, serverNames: List<String>) {
125+
callbacks.forEach { it.onOpenRoom(roomId, serverNames) }
126126
}
127127

128128
override fun onPermalinkClick(data: PermalinkData, pushToBackstack: Boolean) {

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ interface MessagesNavigator {
2020
fun onReportContentClick(eventId: EventId, senderId: UserId)
2121
fun onEditPollClick(eventId: EventId)
2222
fun onPreviewAttachment(attachments: ImmutableList<Attachment>)
23-
fun onNavigateToRoom(roomId: RoomId)
23+
fun onNavigateToRoom(roomId: RoomId, serverNames: List<String>)
2424
}

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import io.element.android.libraries.mediaplayer.api.MediaPlayer
6666
import io.element.android.libraries.ui.strings.CommonStrings
6767
import io.element.android.services.analytics.api.AnalyticsService
6868
import kotlinx.collections.immutable.ImmutableList
69+
import kotlinx.collections.immutable.toImmutableList
6970
import kotlinx.coroutines.CoroutineScope
7071
import kotlinx.coroutines.launch
7172

@@ -213,11 +214,11 @@ class MessagesNode @AssistedInject constructor(
213214
callbacks.forEach { it.onPreviewAttachments(attachments) }
214215
}
215216

216-
override fun onNavigateToRoom(roomId: RoomId) {
217+
override fun onNavigateToRoom(roomId: RoomId, serverNames: List<String>) {
217218
if (roomId == room.roomId) {
218219
displaySameRoomToast()
219220
} else {
220-
val permalinkData = PermalinkData.RoomLink(roomId.toRoomIdOrAlias())
221+
val permalinkData = PermalinkData.RoomLink(roomId.toRoomIdOrAlias(), viaParameters = serverNames.toImmutableList())
221222
callbacks.forEach { it.onPermalinkClick(permalinkData) }
222223
}
223224
}

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ fun MessagesView(
278278
state = state,
279279
onLinkClick = { url, customTab -> onLinkClick(url, customTab) },
280280
onRoomSuccessorClick = { roomId ->
281-
state.timelineState.eventSink(TimelineEvents.NavigateToRoom(roomId = roomId))
281+
state.timelineState.eventSink(TimelineEvents.NavigateToPredecessorOrSuccessorRoom(roomId = roomId))
282282
},
283283
)
284284
},

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ sealed interface TimelineEvents {
3131
data class ComputeVerifiedUserSendFailure(val event: TimelineItem.Event) : EventFromTimelineItem
3232
data class ShowShieldDialog(val messageShield: MessageShield) : EventFromTimelineItem
3333
data class LoadMore(val direction: Timeline.PaginationDirection) : EventFromTimelineItem
34-
data class NavigateToRoom(val roomId: RoomId) : EventFromTimelineItem
34+
35+
/**
36+
* Navigate to the predecessor or successor room of the current room.
37+
*/
38+
data class NavigateToPredecessorOrSuccessorRoom(val roomId: RoomId) : EventFromTimelineItem
3539

3640
/**
3741
* Events coming from a poll item.

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,10 @@ class TimelinePresenter @AssistedInject constructor(
178178
is TimelineEvents.ComputeVerifiedUserSendFailure -> {
179179
resolveVerifiedUserSendFailureState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(event.event))
180180
}
181-
is TimelineEvents.NavigateToRoom -> {
182-
navigator.onNavigateToRoom(event.roomId)
181+
is TimelineEvents.NavigateToPredecessorOrSuccessorRoom -> {
182+
// Navigate to the predecessor or successor room
183+
val serverNames = calculateServerNamesForRoom(room)
184+
navigator.onNavigateToRoom(event.roomId, serverNames)
183185
}
184186
}
185187
}
@@ -353,3 +355,19 @@ private fun FocusRequestState.onFocusEventRender(): FocusRequestState {
353355
else -> this
354356
}
355357
}
358+
359+
// Workaround for not having the server names available, get possible server names from the user ids of the room members
360+
private fun calculateServerNamesForRoom(room: JoinedRoom): List<String> {
361+
// If we have no room members, return right ahead
362+
val serverNames = room.membersStateFlow.value.roomMembers() ?: return emptyList()
363+
364+
// Otherwise get the three most common server names from the user ids of the room members
365+
return serverNames
366+
.mapNotNull { it.userId.domainName }
367+
.groupingBy { it }
368+
.eachCount()
369+
.let { map ->
370+
map.keys.sortedByDescending { map[it] }
371+
}
372+
.take(3)
373+
}

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fun TimelineItemVirtualRow(
4747
roomName = timelineRoomInfo.name,
4848
isDm = timelineRoomInfo.isDm,
4949
onPredecessorRoomClick = { roomId ->
50-
eventSink(TimelineEvents.NavigateToRoom(roomId))
50+
eventSink(TimelineEvents.NavigateToPredecessorOrSuccessorRoom(roomId))
5151
},
5252
)
5353
}

features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class FakeMessagesNavigator(
2121
private val onReportContentClickLambda: (eventId: EventId, senderId: UserId) -> Unit = { _, _ -> lambdaError() },
2222
private val onEditPollClickLambda: (eventId: EventId) -> Unit = { _ -> lambdaError() },
2323
private val onPreviewAttachmentLambda: (attachments: ImmutableList<Attachment>) -> Unit = { _ -> lambdaError() },
24-
private val onNavigateToRoomLambda: (roomId: RoomId) -> Unit = { _ -> lambdaError() }
24+
private val onNavigateToRoomLambda: (roomId: RoomId, serverNames: List<String>) -> Unit = { _, _ -> lambdaError() }
2525
) : MessagesNavigator {
2626
override fun onShowEventDebugInfoClick(eventId: EventId?, debugInfo: TimelineItemDebugInfo) {
2727
onShowEventDebugInfoClickLambda(eventId, debugInfo)
@@ -43,7 +43,7 @@ class FakeMessagesNavigator(
4343
onPreviewAttachmentLambda(attachments)
4444
}
4545

46-
override fun onNavigateToRoom(roomId: RoomId) {
47-
onNavigateToRoomLambda(roomId)
46+
override fun onNavigateToRoom(roomId: RoomId, serverNames: List<String>) {
47+
onNavigateToRoomLambda(roomId, serverNames)
4848
}
4949
}

features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ class MessagesViewTest {
579579
val text = rule.activity.getString(R.string.screen_room_timeline_tombstoned_room_action)
580580
// The bottomsheet subcompose seems to make the node to appear twice
581581
rule.onAllNodesWithText(text).onFirst().performClick()
582-
eventsRecorder.assertSingle(TimelineEvents.NavigateToRoom(successorRoomId))
582+
eventsRecorder.assertSingle(TimelineEvents.NavigateToPredecessorOrSuccessorRoom(successorRoomId))
583583
}
584584

585585
@Test

0 commit comments

Comments
 (0)