Commit 1ec08bec authored by Valere's avatar Valere
Browse files

Fix spaces add room via server

parent d81d971c
...@@ -33,7 +33,7 @@ interface Space { ...@@ -33,7 +33,7 @@ interface Space {
fun spaceSummary(): RoomSummary? fun spaceSummary(): RoomSummary?
suspend fun addChildren(roomId: String, suspend fun addChildren(roomId: String,
viaServers: List<String>, viaServers: List<String>?,
order: String?, order: String?,
autoJoin: Boolean = false, autoJoin: Boolean = false,
suggested: Boolean? = false) suggested: Boolean? = false)
......
...@@ -18,19 +18,13 @@ package org.matrix.android.sdk.internal.session.permalinks ...@@ -18,19 +18,13 @@ package org.matrix.android.sdk.internal.session.permalinks
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.permalinks.PermalinkService.Companion.MATRIX_TO_URL_BASE import org.matrix.android.sdk.api.session.permalinks.PermalinkService.Companion.MATRIX_TO_URL_BASE
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.room.RoomGetter
import java.net.URLEncoder
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Provider
internal class PermalinkFactory @Inject constructor( internal class PermalinkFactory @Inject constructor(
@UserId @UserId
private val userId: String, private val userId: String,
// Use a provider to fix circular Dagger dependency private val viaParameterFinder: ViaParameterFinder
private val roomGetterProvider: Provider<RoomGetter>
) { ) {
fun createPermalink(event: Event): String? { fun createPermalink(event: Event): String? {
...@@ -50,12 +44,12 @@ internal class PermalinkFactory @Inject constructor( ...@@ -50,12 +44,12 @@ internal class PermalinkFactory @Inject constructor(
return if (roomId.isEmpty()) { return if (roomId.isEmpty()) {
null null
} else { } else {
MATRIX_TO_URL_BASE + escape(roomId) + computeViaParams(userId, roomId) MATRIX_TO_URL_BASE + escape(roomId) + viaParameterFinder.computeViaParams(userId, roomId)
} }
} }
fun createPermalink(roomId: String, eventId: String): String { fun createPermalink(roomId: String, eventId: String): String {
return MATRIX_TO_URL_BASE + escape(roomId) + "/" + escape(eventId) + computeViaParams(userId, roomId) return MATRIX_TO_URL_BASE + escape(roomId) + "/" + escape(eventId) + viaParameterFinder.computeViaParams(userId, roomId)
} }
fun getLinkedId(url: String): String? { fun getLinkedId(url: String): String? {
...@@ -66,25 +60,6 @@ internal class PermalinkFactory @Inject constructor( ...@@ -66,25 +60,6 @@ internal class PermalinkFactory @Inject constructor(
} else null } else null
} }
/**
* Compute the via parameters.
* Take up to 3 homeserver domains, taking the most representative one regarding room members and including the
* current user one.
*/
private fun computeViaParams(userId: String, roomId: String): String {
val userHomeserver = userId.substringAfter(":")
return getUserIdsOfJoinedMembers(roomId)
.map { it.substringAfter(":") }
.groupBy { it }
.mapValues { it.value.size }
.toMutableMap()
// Ensure the user homeserver will be included
.apply { this[userHomeserver] = Int.MAX_VALUE }
.let { map -> map.keys.sortedByDescending { map[it] } }
.take(3)
.joinToString(prefix = "?via=", separator = "&via=") { URLEncoder.encode(it, "utf-8") }
}
/** /**
* Escape '/' in id, because it is used as a separator * Escape '/' in id, because it is used as a separator
* *
...@@ -104,15 +79,4 @@ internal class PermalinkFactory @Inject constructor( ...@@ -104,15 +79,4 @@ internal class PermalinkFactory @Inject constructor(
private fun unescape(id: String): String { private fun unescape(id: String): String {
return id.replace("%2F", "/") return id.replace("%2F", "/")
} }
/**
* Get a set of userIds of joined members of a room
*/
private fun getUserIdsOfJoinedMembers(roomId: String): Set<String> {
return roomGetterProvider.get().getRoom(roomId)
?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) })
?.map { it.userId }
.orEmpty()
.toSet()
}
} }
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.internal.session.permalinks
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.room.RoomGetter
import java.net.URLEncoder
import javax.inject.Inject
import javax.inject.Provider
internal class ViaParameterFinder @Inject constructor(
@UserId private val userId: String,
private val roomGetterProvider: Provider<RoomGetter>
) {
fun computeViaParams(roomId: String, max: Int): List<String> {
return computeViaParams(userId, roomId, max)
}
/**
* Compute the via parameters.
* Take up to 3 homeserver domains, taking the most representative one regarding room members and including the
* current user one.
*/
fun computeViaParams(userId: String, roomId: String): String {
return computeViaParams(userId, roomId, 3)
.joinToString(prefix = "?via=", separator = "&via=") { URLEncoder.encode(it, "utf-8") }
}
fun computeViaParams(userId: String, roomId: String, max: Int): List<String> {
val userHomeserver = userId.substringAfter(":")
return getUserIdsOfJoinedMembers(roomId)
.map { it.substringAfter(":") }
.groupBy { it }
.mapValues { it.value.size }
.toMutableMap()
// Ensure the user homeserver will be included
.apply { this[userHomeserver] = Int.MAX_VALUE }
.let { map -> map.keys.sortedByDescending { map[it] } }
.take(max)
}
/**
* Get a set of userIds of joined members of a room
*/
private fun getUserIdsOfJoinedMembers(roomId: String): Set<String> {
return roomGetterProvider.get().getRoom(roomId)
?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) })
?.map { it.userId }
.orEmpty()
.toSet()
}
}
...@@ -40,6 +40,7 @@ import org.matrix.android.sdk.api.session.search.SearchResult ...@@ -40,6 +40,7 @@ import org.matrix.android.sdk.api.session.search.SearchResult
import org.matrix.android.sdk.api.session.space.Space import org.matrix.android.sdk.api.session.space.Space
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
import org.matrix.android.sdk.internal.session.room.state.SendStateTask import org.matrix.android.sdk.internal.session.room.state.SendStateTask
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
import org.matrix.android.sdk.internal.session.search.SearchTask import org.matrix.android.sdk.internal.session.search.SearchTask
...@@ -66,6 +67,7 @@ internal class DefaultRoom @Inject constructor(override val roomId: String, ...@@ -66,6 +67,7 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
private val roomMembersService: MembershipService, private val roomMembersService: MembershipService,
private val roomPushRuleService: RoomPushRuleService, private val roomPushRuleService: RoomPushRuleService,
private val sendStateTask: SendStateTask, private val sendStateTask: SendStateTask,
private val viaParameterFinder: ViaParameterFinder,
private val searchTask: SearchTask) : private val searchTask: SearchTask) :
Room, Room,
TimelineService by timelineService, TimelineService by timelineService,
...@@ -154,6 +156,6 @@ internal class DefaultRoom @Inject constructor(override val roomId: String, ...@@ -154,6 +156,6 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
override fun asSpace(): Space? { override fun asSpace(): Space? {
if (roomSummary()?.roomType != RoomType.SPACE) return null if (roomSummary()?.roomType != RoomType.SPACE) return null
return DefaultSpace(this, roomSummaryDataSource) return DefaultSpace(this, roomSummaryDataSource, viaParameterFinder)
} }
} }
...@@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.session.room ...@@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.session.room
import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
import org.matrix.android.sdk.internal.session.room.alias.DefaultAliasService import org.matrix.android.sdk.internal.session.room.alias.DefaultAliasService
import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService
import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService
...@@ -60,6 +61,7 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService: ...@@ -60,6 +61,7 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService:
private val membershipServiceFactory: DefaultMembershipService.Factory, private val membershipServiceFactory: DefaultMembershipService.Factory,
private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory, private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory,
private val sendStateTask: SendStateTask, private val sendStateTask: SendStateTask,
private val viaParameterFinder: ViaParameterFinder,
private val searchTask: SearchTask) : private val searchTask: SearchTask) :
RoomFactory { RoomFactory {
...@@ -83,7 +85,8 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService: ...@@ -83,7 +85,8 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService:
roomMembersService = membershipServiceFactory.create(roomId), roomMembersService = membershipServiceFactory.create(roomId),
roomPushRuleService = roomPushRuleServiceFactory.create(roomId), roomPushRuleService = roomPushRuleServiceFactory.create(roomId),
sendStateTask = sendStateTask, sendStateTask = sendStateTask,
searchTask = searchTask searchTask = searchTask,
viaParameterFinder = viaParameterFinder
) )
} }
} }
...@@ -24,11 +24,13 @@ import org.matrix.android.sdk.api.session.room.Room ...@@ -24,11 +24,13 @@ import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.space.Space import org.matrix.android.sdk.api.session.space.Space
import org.matrix.android.sdk.api.session.space.model.SpaceChildContent import org.matrix.android.sdk.api.session.space.model.SpaceChildContent
import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
internal class DefaultSpace( internal class DefaultSpace(
private val room: Room, private val room: Room,
private val spaceSummaryDataSource: RoomSummaryDataSource private val spaceSummaryDataSource: RoomSummaryDataSource,
private val viaParameterFinder: ViaParameterFinder
) : Space { ) : Space {
override fun asRoom(): Room { override fun asRoom(): Room {
...@@ -46,15 +48,17 @@ internal class DefaultSpace( ...@@ -46,15 +48,17 @@ internal class DefaultSpace(
} }
override suspend fun addChildren(roomId: String, override suspend fun addChildren(roomId: String,
viaServers: List<String>, viaServers: List<String>?,
order: String?, order: String?,
autoJoin: Boolean, autoJoin: Boolean,
suggested: Boolean?) { suggested: Boolean?) {
// Find best via
room.sendStateEvent( room.sendStateEvent(
eventType = EventType.STATE_SPACE_CHILD, eventType = EventType.STATE_SPACE_CHILD,
stateKey = roomId, stateKey = roomId,
body = SpaceChildContent( body = SpaceChildContent(
via = viaServers, via = viaServers ?: viaParameterFinder.computeViaParams(roomId, 3),
autoJoin = autoJoin, autoJoin = autoJoin,
order = order, order = order,
suggested = suggested suggested = suggested
......
...@@ -832,7 +832,7 @@ class RoomDetailViewModel @AssistedInject constructor( ...@@ -832,7 +832,7 @@ class RoomDetailViewModel @AssistedInject constructor(
session.spaceService().getSpace(spaceId) session.spaceService().getSpace(spaceId)
?.addChildren( ?.addChildren(
state.roomId, state.roomId,
listOf(session.sessionParams.homeServerHost ?: ""), null,
null, null,
true true
) )
...@@ -849,7 +849,7 @@ class RoomDetailViewModel @AssistedInject constructor( ...@@ -849,7 +849,7 @@ class RoomDetailViewModel @AssistedInject constructor(
session.spaceService().getSpace(slashCommandResult.spaceId) session.spaceService().getSpace(slashCommandResult.spaceId)
?.addChildren( ?.addChildren(
room.roomId, room.roomId,
listOf(session.sessionParams.homeServerHost ?: ""), null,
null, null,
false false
) )
......
...@@ -236,10 +236,9 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted private val init ...@@ -236,10 +236,9 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted private val init
if (initialState.parentSpaceId != null) { if (initialState.parentSpaceId != null) {
// add it as a child // add it as a child
try { try {
val via = session.sessionParams.homeServerHost?.let { listOf(it) }.orEmpty()
session.spaceService() session.spaceService()
.getSpace(initialState.parentSpaceId) .getSpace(initialState.parentSpaceId)
?.addChildren(roomId, viaServers = via, order = null) ?.addChildren(roomId, viaServers = null, order = null)
} catch (failure: Throwable) { } catch (failure: Throwable) {
Timber.w(failure, "Failed to add as a child") Timber.w(failure, "Failed to add as a child")
} }
......
...@@ -174,7 +174,7 @@ class SpaceAddRoomsViewModel @AssistedInject constructor( ...@@ -174,7 +174,7 @@ class SpaceAddRoomsViewModel @AssistedInject constructor(
try { try {
session.spaceService().getSpace(initialState.spaceId)!!.addChildren( session.spaceService().getSpace(initialState.spaceId)!!.addChildren(
roomId = roomId, roomId = roomId,
viaServers = listOf(session.sessionParams.homeServerHost ?: ""), viaServers = null,
order = null order = null
) )
completed.add(roomId) completed.add(roomId)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment