Refactors DefaultSpaceService querySpaceChildren

This commit is contained in:
ericdecanini 2022-03-09 18:36:56 +01:00
parent bbc6e8bbce
commit f76f73f8ad
2 changed files with 100 additions and 68 deletions

View File

@ -113,71 +113,107 @@ internal class DefaultSpaceService @Inject constructor(
return peekSpaceTask.execute(PeekSpaceTask.Params(spaceId)) return peekSpaceTask.execute(PeekSpaceTask.Params(spaceId))
} }
override suspend fun querySpaceChildren(spaceId: String, override suspend fun querySpaceChildren(
suggestedOnly: Boolean?, spaceId: String,
limit: Int?, suggestedOnly: Boolean?,
from: String?, limit: Int?,
knownStateList: List<Event>?): SpaceHierarchyData { from: String?,
return resolveSpaceInfoTask.execute( knownStateList: List<Event>?
ResolveSpaceInfoTask.Params( ): SpaceHierarchyData {
spaceId = spaceId, limit = limit, maxDepth = 1, from = from, suggestedOnly = suggestedOnly val spacesResponse = getSpacesResponse(spaceId, suggestedOnly, limit, from)
) val spaceRootResponse = spacesResponse.getRoot(spaceId)
).let { response -> val spaceRoot = spaceRootResponse?.toRoomSummary() ?: createBlankRoomSummary(spaceId)
val spaceDesc = response.rooms?.firstOrNull { it.roomId == spaceId } val spaceChildren = spacesResponse.rooms.mapToSpaceChildInfoList(spaceId, spaceRootResponse, knownStateList)
val root = RoomSummary(
roomId = spaceDesc?.roomId ?: spaceId, return SpaceHierarchyData(
roomType = spaceDesc?.roomType, rootSummary = spaceRoot,
name = spaceDesc?.name ?: "", children = spaceChildren,
displayName = spaceDesc?.name ?: "", childrenState = spaceRootResponse?.childrenState.orEmpty(),
topic = spaceDesc?.topic ?: "", nextToken = spacesResponse.nextBatch
joinedMembersCount = spaceDesc?.numJoinedMembers, )
avatarUrl = spaceDesc?.avatarUrl ?: "",
encryptionEventTs = null,
typingUsers = emptyList(),
isEncrypted = false,
flattenParentIds = emptyList(),
canonicalAlias = spaceDesc?.canonicalAlias,
joinRules = RoomJoinRules.PUBLIC.takeIf { spaceDesc?.worldReadable == true }
)
val children = response.rooms
?.filter { it.roomId != spaceId }
?.flatMap { childSummary ->
(spaceDesc?.childrenState ?: knownStateList)
?.filter { it.stateKey == childSummary.roomId && it.type == EventType.STATE_SPACE_CHILD }
?.mapNotNull { childStateEv ->
// create a child entry for everytime this room is the child of a space
// beware that a room could appear then twice in this list
childStateEv.content.toModel<SpaceChildContent>()?.let { childStateEvContent ->
SpaceChildInfo(
childRoomId = childSummary.roomId,
isKnown = true,
roomType = childSummary.roomType,
name = childSummary.name,
topic = childSummary.topic,
avatarUrl = childSummary.avatarUrl,
order = childStateEvContent.order,
// autoJoin = childStateEvContent.autoJoin ?: false,
viaServers = childStateEvContent.via.orEmpty(),
activeMemberCount = childSummary.numJoinedMembers,
parentRoomId = childStateEv.roomId,
suggested = childStateEvContent.suggested,
canonicalAlias = childSummary.canonicalAlias,
aliases = childSummary.aliases,
worldReadable = childSummary.worldReadable
)
}
}.orEmpty()
}
.orEmpty()
SpaceHierarchyData(
rootSummary = root,
children = children,
childrenState = spaceDesc?.childrenState.orEmpty(),
nextToken = response.nextBatch
)
}
} }
private suspend fun getSpacesResponse(spaceId: String, suggestedOnly: Boolean?, limit: Int?, from: String?) =
resolveSpaceInfoTask.execute(
ResolveSpaceInfoTask.Params(spaceId = spaceId, limit = limit, maxDepth = 1, from = from, suggestedOnly = suggestedOnly)
)
private fun SpacesResponse.getRoot(spaceId: String) = rooms?.firstOrNull { it.roomId == spaceId }
private fun SpaceChildSummaryResponse.toRoomSummary() = RoomSummary(
roomId = roomId,
roomType = roomType,
name = name ?: "",
displayName = name ?: "",
topic = topic ?: "",
joinedMembersCount = numJoinedMembers,
avatarUrl = avatarUrl ?: "",
encryptionEventTs = null,
typingUsers = emptyList(),
isEncrypted = false,
flattenParentIds = emptyList(),
canonicalAlias = canonicalAlias,
joinRules = RoomJoinRules.PUBLIC.takeIf { isWorldReadable }
)
private fun createBlankRoomSummary(spaceId: String) = RoomSummary(
roomId = spaceId,
joinedMembersCount = null,
encryptionEventTs = null,
typingUsers = emptyList(),
isEncrypted = false,
flattenParentIds = emptyList(),
canonicalAlias = null,
joinRules = null
)
private fun List<SpaceChildSummaryResponse>?.mapToSpaceChildInfoList(
spaceId: String,
spaceRootResponse: SpaceChildSummaryResponse?,
knownStateList: List<Event>?,
) = this?.filterIdIsNot(spaceId)
?.toSpaceChildInfoList(spaceRootResponse, knownStateList)
.orEmpty()
private fun List<SpaceChildSummaryResponse>.filterIdIsNot(spaceId: String) = filter { it.roomId != spaceId }
private fun List<SpaceChildSummaryResponse>.toSpaceChildInfoList(
rootRoomResponse: SpaceChildSummaryResponse?,
knownStateList: List<Event>?,
) = flatMap { spaceChildSummary ->
(rootRoomResponse?.childrenState ?: knownStateList)
?.filter { it.isChildOf(spaceChildSummary) }
?.mapNotNull { childStateEvent -> childStateEvent.toSpaceChildInfo(spaceChildSummary) }
.orEmpty()
}
private fun Event.isChildOf(space: SpaceChildSummaryResponse) = stateKey == space.roomId && type == EventType.STATE_SPACE_CHILD
private fun Event.toSpaceChildInfo(summary: SpaceChildSummaryResponse) = content.toModel<SpaceChildContent>()?.let { content ->
createSpaceChildInfo(summary, this, content)
}
private fun createSpaceChildInfo(
summary: SpaceChildSummaryResponse,
stateEvent: Event,
content: SpaceChildContent
) = SpaceChildInfo(
childRoomId = summary.roomId,
isKnown = true,
roomType = summary.roomType,
name = summary.name,
topic = summary.topic,
avatarUrl = summary.avatarUrl,
order = content.order,
viaServers = content.via.orEmpty(),
activeMemberCount = summary.numJoinedMembers,
parentRoomId = stateEvent.roomId,
suggested = content.suggested,
canonicalAlias = summary.canonicalAlias,
aliases = summary.aliases,
worldReadable = summary.isWorldReadable
)
override suspend fun joinSpace(spaceIdOrAlias: String, override suspend fun joinSpace(spaceIdOrAlias: String,
reason: String?, reason: String?,
viaServers: List<String>): JoinSpaceResult { viaServers: List<String>): JoinSpaceResult {
@ -192,10 +228,6 @@ internal class DefaultSpaceService @Inject constructor(
leaveRoomTask.execute(LeaveRoomTask.Params(spaceId, reason)) leaveRoomTask.execute(LeaveRoomTask.Params(spaceId, reason))
} }
// override fun getSpaceParentsOfRoom(roomId: String): List<SpaceSummary> {
// return spaceSummaryDataSource.getParentsOfRoom(roomId)
// }
override suspend fun setSpaceParent(childRoomId: String, parentSpaceId: String, canonical: Boolean, viaServers: List<String>) { override suspend fun setSpaceParent(childRoomId: String, parentSpaceId: String, canonical: Boolean, viaServers: List<String>) {
// Should we perform some validation here?, // Should we perform some validation here?,
// and if client want to bypass, it could use sendStateEvent directly? // and if client want to bypass, it could use sendStateEvent directly?

View File

@ -81,7 +81,7 @@ internal data class SpaceChildSummaryResponse(
* Required. Whether the room may be viewed by guest users without joining. * Required. Whether the room may be viewed by guest users without joining.
*/ */
@Json(name = "world_readable") @Json(name = "world_readable")
val worldReadable: Boolean = false, val isWorldReadable: Boolean = false,
/** /**
* Required. Whether guest users may join the room and participate in it. If they can, * Required. Whether guest users may join the room and participate in it. If they can,