Merge pull request #3401 from vector-im/feature/bca/spaces_fix_3386
Fixes #3386 show space description in explore header
This commit is contained in:
commit
5657da3493
@ -54,7 +54,7 @@ interface PermalinkService {
|
|||||||
*
|
*
|
||||||
* @return the permalink, or null in case of error
|
* @return the permalink, or null in case of error
|
||||||
*/
|
*/
|
||||||
fun createRoomPermalink(roomId: String): String?
|
fun createRoomPermalink(roomId: String, viaServers: List<String>? = null): String?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a permalink for an event. If you have an event you can use [createPermalink]
|
* Creates a permalink for an event. If you have an event you can use [createPermalink]
|
||||||
|
@ -32,5 +32,7 @@ data class SpaceChildInfo(
|
|||||||
val parentRoomId: String?,
|
val parentRoomId: String?,
|
||||||
val suggested: Boolean?,
|
val suggested: Boolean?,
|
||||||
val canonicalAlias: String?,
|
val canonicalAlias: String?,
|
||||||
val aliases: List<String>?
|
val aliases: List<String>?,
|
||||||
|
val worldReadable: Boolean
|
||||||
|
|
||||||
)
|
)
|
||||||
|
@ -28,7 +28,8 @@ sealed class PeekResult {
|
|||||||
val numJoinedMembers: Int?,
|
val numJoinedMembers: Int?,
|
||||||
val roomType: String?,
|
val roomType: String?,
|
||||||
val viaServers: List<String>,
|
val viaServers: List<String>,
|
||||||
val someMembers: List<MatrixItem.UserItem>?
|
val someMembers: List<MatrixItem.UserItem>?,
|
||||||
|
val isPublic: Boolean
|
||||||
) : PeekResult()
|
) : PeekResult()
|
||||||
|
|
||||||
data class PeekingNotAllowed(
|
data class PeekingNotAllowed(
|
||||||
|
@ -20,6 +20,7 @@ import org.matrix.android.sdk.BuildConfig
|
|||||||
import org.matrix.android.sdk.api.session.group.model.GroupSummary
|
import org.matrix.android.sdk.api.session.group.model.GroupSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
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.room.model.RoomType
|
||||||
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoom
|
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoom
|
||||||
import org.matrix.android.sdk.api.session.room.sender.SenderInfo
|
import org.matrix.android.sdk.api.session.room.sender.SenderInfo
|
||||||
@ -38,6 +39,8 @@ sealed class MatrixItem(
|
|||||||
init {
|
init {
|
||||||
if (BuildConfig.DEBUG) checkId()
|
if (BuildConfig.DEBUG) checkId()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class EventItem(override val id: String,
|
data class EventItem(override val id: String,
|
||||||
@ -47,6 +50,8 @@ sealed class MatrixItem(
|
|||||||
init {
|
init {
|
||||||
if (BuildConfig.DEBUG) checkId()
|
if (BuildConfig.DEBUG) checkId()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class RoomItem(override val id: String,
|
data class RoomItem(override val id: String,
|
||||||
@ -56,6 +61,19 @@ sealed class MatrixItem(
|
|||||||
init {
|
init {
|
||||||
if (BuildConfig.DEBUG) checkId()
|
if (BuildConfig.DEBUG) checkId()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class SpaceItem(override val id: String,
|
||||||
|
override val displayName: String? = null,
|
||||||
|
override val avatarUrl: String? = null)
|
||||||
|
: MatrixItem(id, displayName, avatarUrl) {
|
||||||
|
init {
|
||||||
|
if (BuildConfig.DEBUG) checkId()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class RoomAliasItem(override val id: String,
|
data class RoomAliasItem(override val id: String,
|
||||||
@ -68,6 +86,8 @@ sealed class MatrixItem(
|
|||||||
|
|
||||||
// Best name is the id, and we keep the displayName of the room for the case we need the first letter
|
// Best name is the id, and we keep the displayName of the room for the case we need the first letter
|
||||||
override fun getBestName() = id
|
override fun getBestName() = id
|
||||||
|
|
||||||
|
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class GroupItem(override val id: String,
|
data class GroupItem(override val id: String,
|
||||||
@ -80,6 +100,8 @@ sealed class MatrixItem(
|
|||||||
|
|
||||||
// Best name is the id, and we keep the displayName of the room for the case we need the first letter
|
// Best name is the id, and we keep the displayName of the room for the case we need the first letter
|
||||||
override fun getBestName() = id
|
override fun getBestName() = id
|
||||||
|
|
||||||
|
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun getBestName(): String {
|
open fun getBestName(): String {
|
||||||
@ -92,12 +114,15 @@ sealed class MatrixItem(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract fun updateAvatar(newAvatar: String?): MatrixItem
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the prefix as defined in the matrix spec (and not extracted from the id)
|
* Return the prefix as defined in the matrix spec (and not extracted from the id)
|
||||||
*/
|
*/
|
||||||
fun getIdPrefix() = when (this) {
|
fun getIdPrefix() = when (this) {
|
||||||
is UserItem -> '@'
|
is UserItem -> '@'
|
||||||
is EventItem -> '$'
|
is EventItem -> '$'
|
||||||
|
is SpaceItem,
|
||||||
is RoomItem -> '!'
|
is RoomItem -> '!'
|
||||||
is RoomAliasItem -> '#'
|
is RoomAliasItem -> '#'
|
||||||
is GroupItem -> '+'
|
is GroupItem -> '+'
|
||||||
@ -148,7 +173,11 @@ fun User.toMatrixItem() = MatrixItem.UserItem(userId, displayName, avatarUrl)
|
|||||||
|
|
||||||
fun GroupSummary.toMatrixItem() = MatrixItem.GroupItem(groupId, displayName, avatarUrl)
|
fun GroupSummary.toMatrixItem() = MatrixItem.GroupItem(groupId, displayName, avatarUrl)
|
||||||
|
|
||||||
fun RoomSummary.toMatrixItem() = MatrixItem.RoomItem(roomId, displayName, avatarUrl)
|
fun RoomSummary.toMatrixItem() = if (roomType == RoomType.SPACE) {
|
||||||
|
MatrixItem.SpaceItem(roomId, displayName, avatarUrl)
|
||||||
|
} else {
|
||||||
|
MatrixItem.RoomItem(roomId, displayName, avatarUrl)
|
||||||
|
}
|
||||||
|
|
||||||
fun RoomSummary.toRoomAliasMatrixItem() = MatrixItem.RoomAliasItem(canonicalAlias ?: roomId, displayName, avatarUrl)
|
fun RoomSummary.toRoomAliasMatrixItem() = MatrixItem.RoomAliasItem(canonicalAlias ?: roomId, displayName, avatarUrl)
|
||||||
|
|
||||||
@ -159,4 +188,8 @@ fun RoomMemberSummary.toMatrixItem() = MatrixItem.UserItem(userId, displayName,
|
|||||||
|
|
||||||
fun SenderInfo.toMatrixItem() = MatrixItem.UserItem(userId, disambiguatedDisplayName, avatarUrl)
|
fun SenderInfo.toMatrixItem() = MatrixItem.UserItem(userId, disambiguatedDisplayName, avatarUrl)
|
||||||
|
|
||||||
fun SpaceChildInfo.toMatrixItem() = MatrixItem.RoomItem(childRoomId, name ?: canonicalAlias ?: "", avatarUrl)
|
fun SpaceChildInfo.toMatrixItem() = if (roomType == RoomType.SPACE) {
|
||||||
|
MatrixItem.SpaceItem(childRoomId, name ?: canonicalAlias, avatarUrl)
|
||||||
|
} else {
|
||||||
|
MatrixItem.RoomItem(childRoomId, name ?: canonicalAlias, avatarUrl)
|
||||||
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.internal.database.mapper
|
package org.matrix.android.sdk.internal.database.mapper
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||||
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.room.model.SpaceChildInfo
|
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||||
import org.matrix.android.sdk.api.session.room.model.SpaceParentInfo
|
import org.matrix.android.sdk.api.session.room.model.SpaceParentInfo
|
||||||
@ -92,7 +93,8 @@ internal class RoomSummaryMapper @Inject constructor(private val timelineEventMa
|
|||||||
parentRoomId = roomSummaryEntity.roomId,
|
parentRoomId = roomSummaryEntity.roomId,
|
||||||
suggested = it.suggested,
|
suggested = it.suggested,
|
||||||
canonicalAlias = it.childSummaryEntity?.canonicalAlias,
|
canonicalAlias = it.childSummaryEntity?.canonicalAlias,
|
||||||
aliases = it.childSummaryEntity?.aliases?.toList()
|
aliases = it.childSummaryEntity?.aliases?.toList(),
|
||||||
|
worldReadable = it.childSummaryEntity?.joinRules == RoomJoinRules.PUBLIC
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
flattenParentIds = roomSummaryEntity.flattenParentIds?.split("|") ?: emptyList()
|
flattenParentIds = roomSummaryEntity.flattenParentIds?.split("|") ?: emptyList()
|
||||||
|
@ -33,8 +33,8 @@ internal class DefaultPermalinkService @Inject constructor(
|
|||||||
return permalinkFactory.createPermalink(id)
|
return permalinkFactory.createPermalink(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createRoomPermalink(roomId: String): String? {
|
override fun createRoomPermalink(roomId: String, viaServers: List<String>?): String? {
|
||||||
return permalinkFactory.createRoomPermalink(roomId)
|
return permalinkFactory.createRoomPermalink(roomId, viaServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createPermalink(roomId: String, eventId: String): String {
|
override fun createPermalink(roomId: String, eventId: String): String {
|
||||||
|
@ -40,11 +40,18 @@ internal class PermalinkFactory @Inject constructor(
|
|||||||
} else MATRIX_TO_URL_BASE + escape(id)
|
} else MATRIX_TO_URL_BASE + escape(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createRoomPermalink(roomId: String): String? {
|
fun createRoomPermalink(roomId: String, via: List<String>? = null): String? {
|
||||||
return if (roomId.isEmpty()) {
|
return if (roomId.isEmpty()) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
MATRIX_TO_URL_BASE + escape(roomId) + viaParameterFinder.computeViaParams(userId, roomId)
|
buildString {
|
||||||
|
append(MATRIX_TO_URL_BASE)
|
||||||
|
append(escape(roomId))
|
||||||
|
append(
|
||||||
|
via?.takeIf { it.isNotEmpty() }?.let { viaParameterFinder.asUrlViaParameters(it) }
|
||||||
|
?: viaParameterFinder.computeViaParams(userId, roomId)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +39,11 @@ internal class ViaParameterFinder @Inject constructor(
|
|||||||
* current user one.
|
* current user one.
|
||||||
*/
|
*/
|
||||||
fun computeViaParams(userId: String, roomId: String): String {
|
fun computeViaParams(userId: String, roomId: String): String {
|
||||||
return computeViaParams(userId, roomId, 3)
|
return asUrlViaParameters(computeViaParams(userId, roomId, 3))
|
||||||
.joinToString(prefix = "?via=", separator = "&via=") { URLEncoder.encode(it, "utf-8") }
|
}
|
||||||
|
|
||||||
|
fun asUrlViaParameters(viaList: List<String>): String {
|
||||||
|
return viaList.joinToString(prefix = "?via=", separator = "&via=") { URLEncoder.encode(it, "utf-8") }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun computeViaParams(userId: String, roomId: String, max: Int): List<String> {
|
fun computeViaParams(userId: String, roomId: String, max: Int): List<String> {
|
||||||
|
@ -23,6 +23,8 @@ import org.matrix.android.sdk.api.session.events.model.toModel
|
|||||||
import org.matrix.android.sdk.api.session.room.model.RoomAvatarContent
|
import org.matrix.android.sdk.api.session.room.model.RoomAvatarContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomNameContent
|
import org.matrix.android.sdk.api.session.room.model.RoomNameContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
|
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
|
||||||
@ -105,7 +107,8 @@ internal class DefaultPeekRoomTask @Inject constructor(
|
|||||||
numJoinedMembers = publicRepoResult.numJoinedMembers,
|
numJoinedMembers = publicRepoResult.numJoinedMembers,
|
||||||
viaServers = serverList,
|
viaServers = serverList,
|
||||||
roomType = null, // would be nice to get that from directory...
|
roomType = null, // would be nice to get that from directory...
|
||||||
someMembers = null
|
someMembers = null,
|
||||||
|
isPublic = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +146,11 @@ internal class DefaultPeekRoomTask @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val historyVisibility =
|
||||||
|
stateEvents
|
||||||
|
.lastOrNull { it.type == EventType.STATE_ROOM_HISTORY_VISIBILITY && it.stateKey?.isNotEmpty() == true }
|
||||||
|
?.let { it.content?.toModel<RoomHistoryVisibilityContent>()?.historyVisibility }
|
||||||
|
|
||||||
val roomType = stateEvents
|
val roomType = stateEvents
|
||||||
.lastOrNull { it.type == EventType.STATE_ROOM_CREATE }
|
.lastOrNull { it.type == EventType.STATE_ROOM_CREATE }
|
||||||
?.content
|
?.content
|
||||||
@ -158,7 +166,8 @@ internal class DefaultPeekRoomTask @Inject constructor(
|
|||||||
numJoinedMembers = memberCount,
|
numJoinedMembers = memberCount,
|
||||||
roomType = roomType,
|
roomType = roomType,
|
||||||
viaServers = serverList,
|
viaServers = serverList,
|
||||||
someMembers = someMembers
|
someMembers = someMembers,
|
||||||
|
isPublic = historyVisibility == RoomHistoryVisibility.WORLD_READABLE
|
||||||
)
|
)
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
// Would be M_FORBIDDEN if cannot peek :/
|
// Would be M_FORBIDDEN if cannot peek :/
|
||||||
|
@ -147,7 +147,8 @@ internal class DefaultSpaceService @Inject constructor(
|
|||||||
parentRoomId = childStateEv.roomId,
|
parentRoomId = childStateEv.roomId,
|
||||||
suggested = childStateEvContent.suggested,
|
suggested = childStateEvContent.suggested,
|
||||||
canonicalAlias = childSummary.canonicalAlias,
|
canonicalAlias = childSummary.canonicalAlias,
|
||||||
aliases = childSummary.aliases
|
aliases = childSummary.aliases,
|
||||||
|
worldReadable = childSummary.worldReadable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.orEmpty()
|
}.orEmpty()
|
||||||
|
1
newsfragment/3401.bugfix
Normal file
1
newsfragment/3401.bugfix
Normal file
@ -0,0 +1 @@
|
|||||||
|
Fix | On Android it seems to be impossible to view the complete description of a Space (without dev tools)
|
1
newsfragment/3406.bugfix
Normal file
1
newsfragment/3406.bugfix
Normal file
@ -0,0 +1 @@
|
|||||||
|
Fix | Suggest Rooms, Show a detailed view of the room on click
|
@ -71,7 +71,7 @@ abstract class FormEditableSquareAvatarItem : EpoxyModelWithHolder<FormEditableS
|
|||||||
.into(holder.image)
|
.into(holder.image)
|
||||||
}
|
}
|
||||||
matrixItem != null -> {
|
matrixItem != null -> {
|
||||||
avatarRenderer?.renderSpace(matrixItem!!, holder.image)
|
avatarRenderer?.render(matrixItem!!, holder.image)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
avatarRenderer?.clear(holder.image)
|
avatarRenderer?.clear(holder.image)
|
||||||
|
@ -66,24 +66,24 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
|||||||
DrawableImageViewTarget(imageView))
|
DrawableImageViewTarget(imageView))
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
// fun renderSpace(matrixItem: MatrixItem, imageView: ImageView) {
|
||||||
fun renderSpace(matrixItem: MatrixItem, imageView: ImageView, glideRequests: GlideRequests) {
|
// renderSpace(
|
||||||
val placeholder = getSpacePlaceholderDrawable(matrixItem)
|
// matrixItem,
|
||||||
val resolvedUrl = resolvedUrl(matrixItem.avatarUrl)
|
// imageView,
|
||||||
glideRequests
|
// GlideApp.with(imageView)
|
||||||
.load(resolvedUrl)
|
// )
|
||||||
.transform(MultiTransformation(CenterCrop(), RoundedCorners(dimensionConverter.dpToPx(8))))
|
// }
|
||||||
.placeholder(placeholder)
|
//
|
||||||
.into(DrawableImageViewTarget(imageView))
|
// @UiThread
|
||||||
}
|
// private fun renderSpace(matrixItem: MatrixItem, imageView: ImageView, glideRequests: GlideRequests) {
|
||||||
|
// val placeholder = getSpacePlaceholderDrawable(matrixItem)
|
||||||
fun renderSpace(matrixItem: MatrixItem, imageView: ImageView) {
|
// val resolvedUrl = resolvedUrl(matrixItem.avatarUrl)
|
||||||
renderSpace(
|
// glideRequests
|
||||||
matrixItem,
|
// .load(resolvedUrl)
|
||||||
imageView,
|
// .transform(MultiTransformation(CenterCrop(), RoundedCorners(dimensionConverter.dpToPx(8))))
|
||||||
GlideApp.with(imageView)
|
// .placeholder(placeholder)
|
||||||
)
|
// .into(DrawableImageViewTarget(imageView))
|
||||||
}
|
// }
|
||||||
|
|
||||||
fun clear(imageView: ImageView) {
|
fun clear(imageView: ImageView) {
|
||||||
// It can be called after recycler view is destroyed, just silently catch
|
// It can be called after recycler view is destroyed, just silently catch
|
||||||
@ -137,7 +137,16 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
|||||||
target: Target<Drawable>) {
|
target: Target<Drawable>) {
|
||||||
val placeholder = getPlaceholderDrawable(matrixItem)
|
val placeholder = getPlaceholderDrawable(matrixItem)
|
||||||
buildGlideRequest(glideRequests, matrixItem.avatarUrl)
|
buildGlideRequest(glideRequests, matrixItem.avatarUrl)
|
||||||
.apply(RequestOptions.circleCropTransform())
|
.apply {
|
||||||
|
when (matrixItem) {
|
||||||
|
is MatrixItem.SpaceItem -> {
|
||||||
|
transform(MultiTransformation(CenterCrop(), RoundedCorners(dimensionConverter.dpToPx(8))))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
apply(RequestOptions.circleCropTransform())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.placeholder(placeholder)
|
.placeholder(placeholder)
|
||||||
.into(target)
|
.into(target)
|
||||||
}
|
}
|
||||||
@ -197,17 +206,16 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
|||||||
.beginConfig()
|
.beginConfig()
|
||||||
.bold()
|
.bold()
|
||||||
.endConfig()
|
.endConfig()
|
||||||
.buildRound(matrixItem.firstLetterOfDisplayName(), avatarColor)
|
.let {
|
||||||
}
|
when (matrixItem) {
|
||||||
|
is MatrixItem.SpaceItem -> {
|
||||||
@AnyThread
|
it.buildRoundRect(matrixItem.firstLetterOfDisplayName(), avatarColor, dimensionConverter.dpToPx(8))
|
||||||
fun getSpacePlaceholderDrawable(matrixItem: MatrixItem): Drawable {
|
}
|
||||||
val avatarColor = matrixItemColorProvider.getColor(matrixItem)
|
else -> {
|
||||||
return TextDrawable.builder()
|
it.buildRound(matrixItem.firstLetterOfDisplayName(), avatarColor)
|
||||||
.beginConfig()
|
}
|
||||||
.bold()
|
}
|
||||||
.endConfig()
|
}
|
||||||
.buildRoundRect(matrixItem.firstLetterOfDisplayName(), avatarColor, dimensionConverter.dpToPx(8))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PRIVATE API *********************************************************************************
|
// PRIVATE API *********************************************************************************
|
||||||
|
@ -30,4 +30,5 @@ sealed class RoomListAction : VectorViewModelAction {
|
|||||||
data class ToggleTag(val roomId: String, val tag: String) : RoomListAction()
|
data class ToggleTag(val roomId: String, val tag: String) : RoomListAction()
|
||||||
data class LeaveRoom(val roomId: String) : RoomListAction()
|
data class LeaveRoom(val roomId: String) : RoomListAction()
|
||||||
data class JoinSuggestedRoom(val roomId: String, val viaServers: List<String>?) : RoomListAction()
|
data class JoinSuggestedRoom(val roomId: String, val viaServers: List<String>?) : RoomListAction()
|
||||||
|
data class ShowRoomDetails(val roomId: String, val viaServers: List<String>?) : RoomListAction()
|
||||||
}
|
}
|
||||||
|
@ -108,10 +108,11 @@ class RoomListFragment @Inject constructor(
|
|||||||
sharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java)
|
sharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java)
|
||||||
roomListViewModel.observeViewEvents {
|
roomListViewModel.observeViewEvents {
|
||||||
when (it) {
|
when (it) {
|
||||||
is RoomListViewEvents.Loading -> showLoading(it.message)
|
is RoomListViewEvents.Loading -> showLoading(it.message)
|
||||||
is RoomListViewEvents.Failure -> showFailure(it.throwable)
|
is RoomListViewEvents.Failure -> showFailure(it.throwable)
|
||||||
is RoomListViewEvents.SelectRoom -> handleSelectRoom(it)
|
is RoomListViewEvents.SelectRoom -> handleSelectRoom(it)
|
||||||
is RoomListViewEvents.Done -> Unit
|
is RoomListViewEvents.Done -> Unit
|
||||||
|
is RoomListViewEvents.NavigateToMxToBottomSheet -> handleShowMxToLink(it.link)
|
||||||
}.exhaustive
|
}.exhaustive
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,6 +156,10 @@ class RoomListFragment @Inject constructor(
|
|||||||
showErrorInSnackbar(throwable)
|
showErrorInSnackbar(throwable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleShowMxToLink(link: String) {
|
||||||
|
navigator.openMatrixToBottomSheet(requireContext(), link)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
adapterInfosList.onEach { it.contentEpoxyController.removeModelBuildListener(modelBuildListener) }
|
adapterInfosList.onEach { it.contentEpoxyController.removeModelBuildListener(modelBuildListener) }
|
||||||
adapterInfosList.clear()
|
adapterInfosList.clear()
|
||||||
@ -474,6 +479,10 @@ class RoomListFragment @Inject constructor(
|
|||||||
roomListViewModel.handle(RoomListAction.JoinSuggestedRoom(room.childRoomId, room.viaServers))
|
roomListViewModel.handle(RoomListAction.JoinSuggestedRoom(room.childRoomId, room.viaServers))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSuggestedRoomClicked(room: SpaceChildInfo) {
|
||||||
|
roomListViewModel.handle(RoomListAction.ShowRoomDetails(room.childRoomId, room.viaServers))
|
||||||
|
}
|
||||||
|
|
||||||
override fun onRejectRoomInvitation(room: RoomSummary) {
|
override fun onRejectRoomInvitation(room: RoomSummary) {
|
||||||
notificationDrawerManager.clearMemberShipNotificationForRoom(room.roomId)
|
notificationDrawerManager.clearMemberShipNotificationForRoom(room.roomId)
|
||||||
roomListViewModel.handle(RoomListAction.RejectInvitation(room))
|
roomListViewModel.handle(RoomListAction.RejectInvitation(room))
|
||||||
|
@ -26,4 +26,5 @@ interface RoomListListener : FilteredRoomFooterItem.FilteredRoomFooterItemListen
|
|||||||
fun onRejectRoomInvitation(room: RoomSummary)
|
fun onRejectRoomInvitation(room: RoomSummary)
|
||||||
fun onAcceptRoomInvitation(room: RoomSummary)
|
fun onAcceptRoomInvitation(room: RoomSummary)
|
||||||
fun onJoinSuggestedRoom(room: SpaceChildInfo)
|
fun onJoinSuggestedRoom(room: SpaceChildInfo)
|
||||||
|
fun onSuggestedRoomClicked(room: SpaceChildInfo)
|
||||||
}
|
}
|
||||||
|
@ -29,4 +29,5 @@ sealed class RoomListViewEvents : VectorViewEvents {
|
|||||||
|
|
||||||
data class SelectRoom(val roomSummary: RoomSummary) : RoomListViewEvents()
|
data class SelectRoom(val roomSummary: RoomSummary) : RoomListViewEvents()
|
||||||
object Done : RoomListViewEvents()
|
object Done : RoomListViewEvents()
|
||||||
|
data class NavigateToMxToBottomSheet(val link: String) : RoomListViewEvents()
|
||||||
}
|
}
|
||||||
|
@ -161,6 +161,7 @@ class RoomListViewModel @Inject constructor(
|
|||||||
is RoomListAction.ToggleTag -> handleToggleTag(action)
|
is RoomListAction.ToggleTag -> handleToggleTag(action)
|
||||||
is RoomListAction.ToggleSection -> handleToggleSection(action.section)
|
is RoomListAction.ToggleSection -> handleToggleSection(action.section)
|
||||||
is RoomListAction.JoinSuggestedRoom -> handleJoinSuggestedRoom(action)
|
is RoomListAction.JoinSuggestedRoom -> handleJoinSuggestedRoom(action)
|
||||||
|
is RoomListAction.ShowRoomDetails -> handleShowRoomDetails(action)
|
||||||
}.exhaustive
|
}.exhaustive
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,6 +290,12 @@ class RoomListViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleShowRoomDetails(action: RoomListAction.ShowRoomDetails) {
|
||||||
|
session.permalinkService().createRoomPermalink(action.roomId, action.viaServers)?.let {
|
||||||
|
_viewEvents.post(RoomListViewEvents.NavigateToMxToBottomSheet(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleToggleTag(action: RoomListAction.ToggleTag) {
|
private fun handleToggleTag(action: RoomListAction.ToggleTag) {
|
||||||
session.getRoom(action.roomId)?.let { room ->
|
session.getRoom(action.roomId)?.let { room ->
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.app.features.home.room.list
|
package im.vector.app.features.home.room.list
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import com.airbnb.mvrx.Async
|
import com.airbnb.mvrx.Async
|
||||||
import com.airbnb.mvrx.Loading
|
import com.airbnb.mvrx.Loading
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
@ -56,7 +55,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
|
|||||||
|
|
||||||
fun createSuggestion(spaceChildInfo: SpaceChildInfo,
|
fun createSuggestion(spaceChildInfo: SpaceChildInfo,
|
||||||
suggestedRoomJoiningStates: Map<String, Async<Unit>>,
|
suggestedRoomJoiningStates: Map<String, Async<Unit>>,
|
||||||
onJoinClick: View.OnClickListener): VectorEpoxyModel<*> {
|
listener: RoomListListener?): VectorEpoxyModel<*> {
|
||||||
return SpaceChildInfoItem_()
|
return SpaceChildInfoItem_()
|
||||||
.id("sug_${spaceChildInfo.childRoomId}")
|
.id("sug_${spaceChildInfo.childRoomId}")
|
||||||
.matrixItem(spaceChildInfo.toMatrixItem())
|
.matrixItem(spaceChildInfo.toMatrixItem())
|
||||||
@ -65,7 +64,8 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
|
|||||||
.buttonLabel(stringProvider.getString(R.string.join))
|
.buttonLabel(stringProvider.getString(R.string.join))
|
||||||
.loading(suggestedRoomJoiningStates[spaceChildInfo.childRoomId] is Loading)
|
.loading(suggestedRoomJoiningStates[spaceChildInfo.childRoomId] is Loading)
|
||||||
.memberCount(spaceChildInfo.activeMemberCount ?: 0)
|
.memberCount(spaceChildInfo.activeMemberCount ?: 0)
|
||||||
.buttonClickListener(onJoinClick)
|
.buttonClickListener(DebouncedClickListener({ listener?.onJoinSuggestedRoom(spaceChildInfo) }))
|
||||||
|
.itemClickListener(DebouncedClickListener({ listener?.onSuggestedRoomClicked(spaceChildInfo) }))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createInvitationItem(roomSummary: RoomSummary,
|
private fun createInvitationItem(roomSummary: RoomSummary,
|
||||||
|
@ -48,7 +48,6 @@ abstract class SpaceChildInfoItem : VectorEpoxyModel<SpaceChildInfoItem.Holder>(
|
|||||||
|
|
||||||
@EpoxyAttribute var memberCount: Int = 0
|
@EpoxyAttribute var memberCount: Int = 0
|
||||||
@EpoxyAttribute var loading: Boolean = false
|
@EpoxyAttribute var loading: Boolean = false
|
||||||
@EpoxyAttribute var space: Boolean = false
|
|
||||||
|
|
||||||
@EpoxyAttribute var buttonLabel: String? = null
|
@EpoxyAttribute var buttonLabel: String? = null
|
||||||
|
|
||||||
@ -63,12 +62,8 @@ abstract class SpaceChildInfoItem : VectorEpoxyModel<SpaceChildInfoItem.Holder>(
|
|||||||
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||||
itemLongClickListener?.onLongClick(it) ?: false
|
itemLongClickListener?.onLongClick(it) ?: false
|
||||||
}
|
}
|
||||||
holder.titleView.text = matrixItem.getBestName()
|
holder.titleView.text = matrixItem.displayName ?: holder.rootView.context.getString(R.string.unnamed_room)
|
||||||
if (space) {
|
avatarRenderer.render(matrixItem, holder.avatarImageView)
|
||||||
avatarRenderer.renderSpace(matrixItem, holder.avatarImageView)
|
|
||||||
} else {
|
|
||||||
avatarRenderer.render(matrixItem, holder.avatarImageView)
|
|
||||||
}
|
|
||||||
|
|
||||||
holder.descriptionText.text = span {
|
holder.descriptionText.text = span {
|
||||||
span {
|
span {
|
||||||
|
@ -24,11 +24,7 @@ class SuggestedRoomListController(
|
|||||||
|
|
||||||
override fun buildModels(data: SuggestedRoomInfo?) {
|
override fun buildModels(data: SuggestedRoomInfo?) {
|
||||||
data?.rooms?.forEach { info ->
|
data?.rooms?.forEach { info ->
|
||||||
roomSummaryItemFactory.createSuggestion(info, data.joinEcho) {
|
add(roomSummaryItemFactory.createSuggestion(info, data.joinEcho, listener))
|
||||||
listener?.onJoinSuggestedRoom(info)
|
|
||||||
}.let {
|
|
||||||
add(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,14 +41,15 @@ data class MatrixToBottomSheetState(
|
|||||||
|
|
||||||
sealed class RoomInfoResult {
|
sealed class RoomInfoResult {
|
||||||
data class FullInfo(
|
data class FullInfo(
|
||||||
val roomItem: MatrixItem.RoomItem,
|
val roomItem: MatrixItem,
|
||||||
val name: String,
|
val name: String,
|
||||||
val topic: String,
|
val topic: String,
|
||||||
val memberCount: Int?,
|
val memberCount: Int?,
|
||||||
val alias: String?,
|
val alias: String?,
|
||||||
val membership: Membership,
|
val membership: Membership,
|
||||||
val roomType: String?,
|
val roomType: String?,
|
||||||
val viaServers: List<String>?
|
val viaServers: List<String>?,
|
||||||
|
val isPublic: Boolean
|
||||||
) : RoomInfoResult()
|
) : RoomInfoResult()
|
||||||
|
|
||||||
data class PartialInfo(
|
data class PartialInfo(
|
||||||
|
@ -118,11 +118,9 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
|
|||||||
session.getRoom(permalinkData.roomIdOrAlias)
|
session.getRoom(permalinkData.roomIdOrAlias)
|
||||||
}
|
}
|
||||||
?.roomSummary()
|
?.roomSummary()
|
||||||
// don't take if not active, as it could be outdated
|
// don't take if not Join, as it could be outdated
|
||||||
?.takeIf { it.membership.isActive() }
|
?.takeIf { it.membership == Membership.JOIN }
|
||||||
// XXX fix that
|
if (knownRoom != null) {
|
||||||
val forceRefresh = true
|
|
||||||
if (!forceRefresh && knownRoom != null) {
|
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
roomPeekResult = Success(
|
roomPeekResult = Success(
|
||||||
@ -134,7 +132,8 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
|
|||||||
alias = knownRoom.canonicalAlias,
|
alias = knownRoom.canonicalAlias,
|
||||||
membership = knownRoom.membership,
|
membership = knownRoom.membership,
|
||||||
roomType = knownRoom.roomType,
|
roomType = knownRoom.roomType,
|
||||||
viaServers = null
|
viaServers = null,
|
||||||
|
isPublic = knownRoom.isPublic
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -150,7 +149,8 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
|
|||||||
alias = peekResult.alias,
|
alias = peekResult.alias,
|
||||||
membership = knownRoom?.membership ?: Membership.NONE,
|
membership = knownRoom?.membership ?: Membership.NONE,
|
||||||
roomType = peekResult.roomType,
|
roomType = peekResult.roomType,
|
||||||
viaServers = peekResult.viaServers.takeIf { it.isNotEmpty() } ?: permalinkData.viaParameters
|
viaServers = peekResult.viaServers.takeIf { it.isNotEmpty() } ?: permalinkData.viaParameters,
|
||||||
|
isPublic = peekResult.isPublic
|
||||||
).also {
|
).also {
|
||||||
peekResult.someMembers?.let { checkForKnownMembers(it) }
|
peekResult.someMembers?.let { checkForKnownMembers(it) }
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,8 @@ import org.matrix.android.sdk.api.session.room.model.RoomType
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class MatrixToRoomSpaceFragment @Inject constructor(
|
class MatrixToRoomSpaceFragment @Inject constructor(
|
||||||
private val avatarRenderer: AvatarRenderer
|
private val avatarRenderer: AvatarRenderer,
|
||||||
|
private val spaceCardRenderer: SpaceCardRenderer
|
||||||
) : VectorBaseFragment<FragmentMatrixToRoomSpaceCardBinding>() {
|
) : VectorBaseFragment<FragmentMatrixToRoomSpaceCardBinding>() {
|
||||||
|
|
||||||
private val sharedViewModel: MatrixToBottomSheetViewModel by parentFragmentViewModel()
|
private val sharedViewModel: MatrixToBottomSheetViewModel by parentFragmentViewModel()
|
||||||
@ -78,12 +79,19 @@ class MatrixToRoomSpaceFragment @Inject constructor(
|
|||||||
when (val peek = item.invoke()) {
|
when (val peek = item.invoke()) {
|
||||||
is RoomInfoResult.FullInfo -> {
|
is RoomInfoResult.FullInfo -> {
|
||||||
val matrixItem = peek.roomItem
|
val matrixItem = peek.roomItem
|
||||||
|
avatarRenderer.render(matrixItem, views.matrixToCardAvatar)
|
||||||
if (peek.roomType == RoomType.SPACE) {
|
if (peek.roomType == RoomType.SPACE) {
|
||||||
views.matrixToBetaTag.isVisible = true
|
views.matrixToBetaTag.isVisible = true
|
||||||
avatarRenderer.renderSpace(matrixItem, views.matrixToCardAvatar)
|
views.matrixToAccessImage.isVisible = true
|
||||||
|
if (peek.isPublic) {
|
||||||
|
views.matrixToAccessText.setTextOrHide(context?.getString(R.string.public_space))
|
||||||
|
views.matrixToAccessImage.setImageResource(R.drawable.ic_public_room)
|
||||||
|
} else {
|
||||||
|
views.matrixToAccessText.setTextOrHide(context?.getString(R.string.private_space))
|
||||||
|
views.matrixToAccessImage.setImageResource(R.drawable.ic_room_private)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
views.matrixToBetaTag.isVisible = false
|
views.matrixToBetaTag.isVisible = false
|
||||||
avatarRenderer.render(matrixItem, views.matrixToCardAvatar)
|
|
||||||
}
|
}
|
||||||
views.matrixToCardNameText.setTextOrHide(peek.name)
|
views.matrixToCardNameText.setTextOrHide(peek.name)
|
||||||
views.matrixToCardAliasText.setTextOrHide(peek.alias)
|
views.matrixToCardAliasText.setTextOrHide(peek.alias)
|
||||||
@ -166,25 +174,12 @@ class MatrixToRoomSpaceFragment @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val images = listOf(views.knownMember1, views.knownMember2, views.knownMember3, views.knownMember4, views.knownMember5)
|
listOf(views.knownMember1, views.knownMember2, views.knownMember3, views.knownMember4, views.knownMember5)
|
||||||
.onEach { it.isGone = true }
|
.onEach { it.isGone = true }
|
||||||
when (state.peopleYouKnow) {
|
when (state.peopleYouKnow) {
|
||||||
is Success -> {
|
is Success -> {
|
||||||
val someYouKnow = state.peopleYouKnow.invoke()
|
val someYouKnow = state.peopleYouKnow.invoke()
|
||||||
if (someYouKnow.isEmpty()) {
|
spaceCardRenderer.renderPeopleYouKnow(views, someYouKnow)
|
||||||
views.peopleYouMayKnowText.isVisible = false
|
|
||||||
} else {
|
|
||||||
someYouKnow.forEachIndexed { index, item ->
|
|
||||||
images[index].isVisible = true
|
|
||||||
avatarRenderer.render(item, images[index])
|
|
||||||
}
|
|
||||||
views.peopleYouMayKnowText.setTextOrHide(
|
|
||||||
resources.getQuantityString(R.plurals.space_people_you_know,
|
|
||||||
someYouKnow.count(),
|
|
||||||
someYouKnow.count()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
views.peopleYouMayKnowText.isVisible = false
|
views.peopleYouMayKnowText.isVisible = false
|
||||||
|
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 New Vector Ltd
|
||||||
|
*
|
||||||
|
* 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 im.vector.app.features.matrixto
|
||||||
|
|
||||||
|
import androidx.core.view.isGone
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.extensions.setTextOrHide
|
||||||
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
import im.vector.app.databinding.FragmentMatrixToRoomSpaceCardBinding
|
||||||
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
|
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
||||||
|
import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod
|
||||||
|
import im.vector.app.features.home.room.detail.timeline.tools.linkify
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||||
|
import org.matrix.android.sdk.api.session.user.model.User
|
||||||
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class SpaceCardRenderer @Inject constructor(
|
||||||
|
private val avatarRenderer: AvatarRenderer,
|
||||||
|
private val stringProvider: StringProvider
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun render(spaceSummary: RoomSummary?,
|
||||||
|
peopleYouKnow: List<User>,
|
||||||
|
matrixLinkCallback: TimelineEventController.UrlClickCallback?,
|
||||||
|
inCard: FragmentMatrixToRoomSpaceCardBinding) {
|
||||||
|
if (spaceSummary == null) {
|
||||||
|
inCard.matrixToCardContentVisibility.isVisible = false
|
||||||
|
inCard.matrixToCardButtonLoading.isVisible = true
|
||||||
|
} else {
|
||||||
|
inCard.matrixToCardContentVisibility.isVisible = true
|
||||||
|
inCard.matrixToCardButtonLoading.isVisible = false
|
||||||
|
avatarRenderer.render(spaceSummary.toMatrixItem(), inCard.matrixToCardAvatar)
|
||||||
|
inCard.matrixToCardNameText.text = spaceSummary.name
|
||||||
|
inCard.matrixToBetaTag.isVisible = true
|
||||||
|
inCard.matrixToCardAliasText.setTextOrHide(spaceSummary.canonicalAlias)
|
||||||
|
inCard.matrixToCardDescText.setTextOrHide(spaceSummary.topic.linkify(matrixLinkCallback))
|
||||||
|
if (spaceSummary.isPublic) {
|
||||||
|
inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(R.string.public_space))
|
||||||
|
inCard.matrixToAccessImage.isVisible = true
|
||||||
|
inCard.matrixToAccessImage.setImageResource(R.drawable.ic_public_room)
|
||||||
|
} else {
|
||||||
|
inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(R.string.private_space))
|
||||||
|
inCard.matrixToAccessImage.isVisible = true
|
||||||
|
inCard.matrixToAccessImage.setImageResource(R.drawable.ic_room_private)
|
||||||
|
}
|
||||||
|
val memberCount = spaceSummary.otherMemberIds.size
|
||||||
|
if (memberCount != 0) {
|
||||||
|
inCard.matrixToMemberPills.isVisible = true
|
||||||
|
inCard.spaceChildMemberCountText.text = stringProvider.getQuantityString(R.plurals.room_title_members, memberCount, memberCount)
|
||||||
|
} else {
|
||||||
|
// hide the pill
|
||||||
|
inCard.matrixToMemberPills.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPeopleYouKnow(inCard, peopleYouKnow.map { it.toMatrixItem() })
|
||||||
|
}
|
||||||
|
inCard.matrixToCardDescText.movementMethod = createLinkMovementMethod(object : TimelineEventController.UrlClickCallback {
|
||||||
|
override fun onUrlClicked(url: String, title: String): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUrlLongClicked(url: String): Boolean {
|
||||||
|
// host.callback?.onUrlInTopicLongClicked(url)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun render(spaceChildInfo: SpaceChildInfo?,
|
||||||
|
peopleYouKnow: List<User>,
|
||||||
|
matrixLinkCallback: TimelineEventController.UrlClickCallback?,
|
||||||
|
inCard: FragmentMatrixToRoomSpaceCardBinding) {
|
||||||
|
if (spaceChildInfo == null) {
|
||||||
|
inCard.matrixToCardContentVisibility.isVisible = false
|
||||||
|
inCard.matrixToCardButtonLoading.isVisible = true
|
||||||
|
} else {
|
||||||
|
inCard.matrixToCardContentVisibility.isVisible = true
|
||||||
|
inCard.matrixToCardButtonLoading.isVisible = false
|
||||||
|
avatarRenderer.render(spaceChildInfo.toMatrixItem(), inCard.matrixToCardAvatar)
|
||||||
|
inCard.matrixToCardNameText.setTextOrHide(spaceChildInfo.name)
|
||||||
|
inCard.matrixToBetaTag.isVisible = true
|
||||||
|
inCard.matrixToCardAliasText.setTextOrHide(spaceChildInfo.canonicalAlias)
|
||||||
|
inCard.matrixToCardDescText.setTextOrHide(spaceChildInfo.topic?.linkify(matrixLinkCallback))
|
||||||
|
if (spaceChildInfo.worldReadable) {
|
||||||
|
inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(R.string.public_space))
|
||||||
|
inCard.matrixToAccessImage.isVisible = true
|
||||||
|
inCard.matrixToAccessImage.setImageResource(R.drawable.ic_public_room)
|
||||||
|
} else {
|
||||||
|
inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(R.string.private_space))
|
||||||
|
inCard.matrixToAccessImage.isVisible = true
|
||||||
|
inCard.matrixToAccessImage.setImageResource(R.drawable.ic_room_private)
|
||||||
|
}
|
||||||
|
val memberCount = spaceChildInfo.activeMemberCount ?: 0
|
||||||
|
if (memberCount != 0) {
|
||||||
|
inCard.matrixToMemberPills.isVisible = true
|
||||||
|
inCard.spaceChildMemberCountText.text = stringProvider.getQuantityString(R.plurals.room_title_members, memberCount, memberCount)
|
||||||
|
} else {
|
||||||
|
// hide the pill
|
||||||
|
inCard.matrixToMemberPills.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPeopleYouKnow(inCard, peopleYouKnow.map { it.toMatrixItem() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun renderPeopleYouKnow(inCard: FragmentMatrixToRoomSpaceCardBinding, peopleYouKnow: List<MatrixItem.UserItem>) {
|
||||||
|
val images = listOf(
|
||||||
|
inCard.knownMember1,
|
||||||
|
inCard.knownMember2,
|
||||||
|
inCard.knownMember3,
|
||||||
|
inCard.knownMember4,
|
||||||
|
inCard.knownMember5
|
||||||
|
).onEach { it.isGone = true }
|
||||||
|
|
||||||
|
if (peopleYouKnow.isEmpty()) {
|
||||||
|
inCard.peopleYouMayKnowText.isVisible = false
|
||||||
|
} else {
|
||||||
|
peopleYouKnow.forEachIndexed { index, item ->
|
||||||
|
images[index].isVisible = true
|
||||||
|
avatarRenderer.render(item, images[index])
|
||||||
|
}
|
||||||
|
inCard.peopleYouMayKnowText.setTextOrHide(
|
||||||
|
stringProvider.getQuantityString(R.plurals.space_people_you_know,
|
||||||
|
peopleYouKnow.count(),
|
||||||
|
peopleYouKnow.count()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -245,7 +245,7 @@ class ImageContentRenderer @Inject constructor(private val localFilesHelper: Loc
|
|||||||
val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
|
val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
|
||||||
val resolvedUrl = when (mode) {
|
val resolvedUrl = when (mode) {
|
||||||
Mode.FULL_SIZE,
|
Mode.FULL_SIZE,
|
||||||
Mode.STICKER -> resolveUrl(data)
|
Mode.STICKER -> resolveUrl(data)
|
||||||
Mode.THUMBNAIL -> contentUrlResolver.resolveThumbnail(data.url, size.width, size.height, ContentUrlResolver.ThumbnailMethod.SCALE)
|
Mode.THUMBNAIL -> contentUrlResolver.resolveThumbnail(data.url, size.width, size.height, ContentUrlResolver.ThumbnailMethod.SCALE)
|
||||||
}
|
}
|
||||||
// Fallback to base url
|
// Fallback to base url
|
||||||
@ -313,7 +313,7 @@ class ImageContentRenderer @Inject constructor(private val localFilesHelper: Loc
|
|||||||
finalHeight = min(maxImageWidth * height / width, maxImageHeight)
|
finalHeight = min(maxImageWidth * height / width, maxImageHeight)
|
||||||
finalWidth = finalHeight * width / height
|
finalWidth = finalHeight * width / height
|
||||||
}
|
}
|
||||||
Mode.STICKER -> {
|
Mode.STICKER -> {
|
||||||
// limit on width
|
// limit on width
|
||||||
val maxWidthDp = min(dimensionConverter.dpToPx(120), maxImageWidth / 2)
|
val maxWidthDp = min(dimensionConverter.dpToPx(120), maxImageWidth / 2)
|
||||||
finalWidth = min(dimensionConverter.dpToPx(width), maxWidthDp)
|
finalWidth = min(dimensionConverter.dpToPx(width), maxWidthDp)
|
||||||
|
@ -68,16 +68,14 @@ class RoomSettingsController @Inject constructor(
|
|||||||
id("avatar")
|
id("avatar")
|
||||||
enabled(data.actionPermissions.canChangeAvatar)
|
enabled(data.actionPermissions.canChangeAvatar)
|
||||||
when (val avatarAction = data.avatarAction) {
|
when (val avatarAction = data.avatarAction) {
|
||||||
RoomSettingsViewState.AvatarAction.None -> {
|
RoomSettingsViewState.AvatarAction.None -> {
|
||||||
// Use the current value
|
// Use the current value
|
||||||
avatarRenderer(host.avatarRenderer)
|
avatarRenderer(host.avatarRenderer)
|
||||||
// We do not want to use the fallback avatar url, which can be the other user avatar, or the current user avatar.
|
// We do not want to use the fallback avatar url, which can be the other user avatar, or the current user avatar.
|
||||||
matrixItem(roomSummary.toMatrixItem().copy(avatarUrl = data.currentRoomAvatarUrl))
|
matrixItem(roomSummary.toMatrixItem().updateAvatar(data.currentRoomAvatarUrl))
|
||||||
}
|
}
|
||||||
RoomSettingsViewState.AvatarAction.DeleteAvatar ->
|
RoomSettingsViewState.AvatarAction.DeleteAvatar -> imageUri(null)
|
||||||
imageUri(null)
|
is RoomSettingsViewState.AvatarAction.UpdateAvatar -> imageUri(avatarAction.newAvatarUri)
|
||||||
is RoomSettingsViewState.AvatarAction.UpdateAvatar ->
|
|
||||||
imageUri(avatarAction.newAvatarUri)
|
|
||||||
}
|
}
|
||||||
clickListener { host.callback?.onAvatarChange() }
|
clickListener { host.callback?.onAvatarChange() }
|
||||||
deleteListener { host.callback?.onAvatarDelete() }
|
deleteListener { host.callback?.onAvatarDelete() }
|
||||||
|
@ -96,7 +96,7 @@ class SpaceSettingsMenuBottomSheet : VectorBaseBottomSheetDialogFragment<BottomS
|
|||||||
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
||||||
val roomSummary = session.getRoomSummary(spaceArgs.spaceId)
|
val roomSummary = session.getRoomSummary(spaceArgs.spaceId)
|
||||||
roomSummary?.toMatrixItem()?.let {
|
roomSummary?.toMatrixItem()?.let {
|
||||||
avatarRenderer.renderSpace(it, views.spaceAvatarImageView)
|
avatarRenderer.render(it, views.spaceAvatarImageView)
|
||||||
}
|
}
|
||||||
views.spaceNameView.text = roomSummary?.displayName
|
views.spaceNameView.text = roomSummary?.displayName
|
||||||
views.spaceDescription.setTextOrHide(roomSummary?.topic?.takeIf { it.isNotEmpty() })
|
views.spaceDescription.setTextOrHide(roomSummary?.topic?.takeIf { it.isNotEmpty() })
|
||||||
|
@ -87,7 +87,7 @@ abstract class SpaceSummaryItem : VectorEpoxyModel<SpaceSummaryItem.Holder>() {
|
|||||||
holder.indentSpace.isVisible = indent > 0
|
holder.indentSpace.isVisible = indent > 0
|
||||||
holder.separator.isVisible = showSeparator
|
holder.separator.isVisible = showSeparator
|
||||||
|
|
||||||
avatarRenderer.renderSpace(matrixItem, holder.avatarImageView)
|
avatarRenderer.render(matrixItem, holder.avatarImageView)
|
||||||
holder.counterBadgeView.render(countState)
|
holder.counterBadgeView.render(countState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ abstract class SubSpaceSummaryItem : VectorEpoxyModel<SubSpaceSummaryItem.Holder
|
|||||||
width = indent * 30
|
width = indent * 30
|
||||||
}
|
}
|
||||||
|
|
||||||
avatarRenderer.renderSpace(matrixItem, holder.avatarImageView)
|
avatarRenderer.render(matrixItem, holder.avatarImageView)
|
||||||
holder.counterBadgeView.render(countState)
|
holder.counterBadgeView.render(countState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class SpaceDetailEpoxyController @Inject constructor(
|
|||||||
enabled(true)
|
enabled(true)
|
||||||
imageUri(data?.avatarUri)
|
imageUri(data?.avatarUri)
|
||||||
avatarRenderer(host.avatarRenderer)
|
avatarRenderer(host.avatarRenderer)
|
||||||
matrixItem(data?.name?.let { MatrixItem.RoomItem("!", it, null).takeIf { !it.displayName.isNullOrBlank() } })
|
matrixItem(data?.name?.let { MatrixItem.SpaceItem("!", it, null).takeIf { !it.displayName.isNullOrBlank() } })
|
||||||
clickListener { host.listener?.onAvatarChange() }
|
clickListener { host.listener?.onAvatarChange() }
|
||||||
deleteListener { host.listener?.onAvatarDelete() }
|
deleteListener { host.listener?.onAvatarDelete() }
|
||||||
}
|
}
|
||||||
|
@ -122,13 +122,15 @@ class SpaceDirectoryController @Inject constructor(
|
|||||||
val isSpace = info.roomType == RoomType.SPACE
|
val isSpace = info.roomType == RoomType.SPACE
|
||||||
val isJoined = data?.joinedRoomsIds?.contains(info.childRoomId) == true
|
val isJoined = data?.joinedRoomsIds?.contains(info.childRoomId) == true
|
||||||
val isLoading = data?.changeMembershipStates?.get(info.childRoomId)?.isInProgress() ?: false
|
val isLoading = data?.changeMembershipStates?.get(info.childRoomId)?.isInProgress() ?: false
|
||||||
|
// if it's known use that matrixItem because it would have a better computed name
|
||||||
|
val matrixItem = data?.knownRoomSummaries?.find { it.roomId == info.childRoomId }?.toMatrixItem()
|
||||||
|
?: info.toMatrixItem()
|
||||||
spaceChildInfoItem {
|
spaceChildInfoItem {
|
||||||
id(info.childRoomId)
|
id(info.childRoomId)
|
||||||
matrixItem(info.toMatrixItem())
|
matrixItem(matrixItem)
|
||||||
avatarRenderer(host.avatarRenderer)
|
avatarRenderer(host.avatarRenderer)
|
||||||
topic(info.topic)
|
topic(info.topic)
|
||||||
memberCount(info.activeMemberCount ?: 0)
|
memberCount(info.activeMemberCount ?: 0)
|
||||||
space(isSpace)
|
|
||||||
loading(isLoading)
|
loading(isLoading)
|
||||||
buttonLabel(
|
buttonLabel(
|
||||||
if (isJoined) host.stringProvider.getString(R.string.action_open)
|
if (isJoined) host.stringProvider.getString(R.string.action_open)
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package im.vector.app.features.spaces.explore
|
package im.vector.app.features.spaces.explore
|
||||||
|
|
||||||
|
import android.content.DialogInterface
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -23,19 +24,33 @@ import android.view.Menu
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.core.text.toSpannable
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import com.airbnb.mvrx.activityViewModel
|
import com.airbnb.mvrx.activityViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.dialogs.withColoredButton
|
||||||
import im.vector.app.core.extensions.cleanup
|
import im.vector.app.core.extensions.cleanup
|
||||||
import im.vector.app.core.extensions.configureWith
|
import im.vector.app.core.extensions.configureWith
|
||||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||||
import im.vector.app.core.platform.OnBackPressed
|
import im.vector.app.core.platform.OnBackPressed
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
|
import im.vector.app.core.resources.ColorProvider
|
||||||
|
import im.vector.app.core.utils.colorizeMatchingText
|
||||||
|
import im.vector.app.core.utils.isValidUrl
|
||||||
|
import im.vector.app.core.utils.openUrlInExternalBrowser
|
||||||
import im.vector.app.databinding.FragmentRoomDirectoryPickerBinding
|
import im.vector.app.databinding.FragmentRoomDirectoryPickerBinding
|
||||||
|
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
||||||
|
import im.vector.app.features.matrixto.SpaceCardRenderer
|
||||||
|
import im.vector.app.features.permalink.PermalinkHandler
|
||||||
import im.vector.app.features.spaces.manage.ManageType
|
import im.vector.app.features.spaces.manage.ManageType
|
||||||
import im.vector.app.features.spaces.manage.SpaceManageActivity
|
import im.vector.app.features.spaces.manage.SpaceManageActivity
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||||
|
import java.net.URL
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@ -44,9 +59,13 @@ data class SpaceDirectoryArgs(
|
|||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
class SpaceDirectoryFragment @Inject constructor(
|
class SpaceDirectoryFragment @Inject constructor(
|
||||||
private val epoxyController: SpaceDirectoryController
|
private val epoxyController: SpaceDirectoryController,
|
||||||
|
private val permalinkHandler: PermalinkHandler,
|
||||||
|
private val spaceCardRenderer: SpaceCardRenderer,
|
||||||
|
private val colorProvider: ColorProvider
|
||||||
) : VectorBaseFragment<FragmentRoomDirectoryPickerBinding>(),
|
) : VectorBaseFragment<FragmentRoomDirectoryPickerBinding>(),
|
||||||
SpaceDirectoryController.InteractionListener,
|
SpaceDirectoryController.InteractionListener,
|
||||||
|
TimelineEventController.UrlClickCallback,
|
||||||
OnBackPressed {
|
OnBackPressed {
|
||||||
|
|
||||||
override fun getMenuRes() = R.menu.menu_space_directory
|
override fun getMenuRes() = R.menu.menu_space_directory
|
||||||
@ -71,6 +90,9 @@ class SpaceDirectoryFragment @Inject constructor(
|
|||||||
viewModel.selectSubscribe(this, SpaceDirectoryState::canAddRooms) {
|
viewModel.selectSubscribe(this, SpaceDirectoryState::canAddRooms) {
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
views.spaceCard.matrixToCardMainButton.isVisible = false
|
||||||
|
views.spaceCard.matrixToCardSecondaryButton.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
@ -82,10 +104,21 @@ class SpaceDirectoryFragment @Inject constructor(
|
|||||||
override fun invalidate() = withState(viewModel) { state ->
|
override fun invalidate() = withState(viewModel) { state ->
|
||||||
epoxyController.setData(state)
|
epoxyController.setData(state)
|
||||||
|
|
||||||
val title = state.hierarchyStack.lastOrNull()?.let { currentParent ->
|
val currentParent = state.hierarchyStack.lastOrNull()?.let { currentParent ->
|
||||||
state.spaceSummaryApiResult.invoke()?.firstOrNull { it.childRoomId == currentParent }
|
state.spaceSummaryApiResult.invoke()?.firstOrNull { it.childRoomId == currentParent }
|
||||||
}?.name ?: getString(R.string.space_explore_activity_title)
|
}
|
||||||
views.toolbar.title = title
|
|
||||||
|
if (currentParent == null) {
|
||||||
|
val title = getString(R.string.space_explore_activity_title)
|
||||||
|
views.toolbar.title = title
|
||||||
|
|
||||||
|
spaceCardRenderer.render(state.spaceSummary.invoke(), emptyList(), this, views.spaceCard)
|
||||||
|
} else {
|
||||||
|
val title = currentParent.name ?: currentParent.canonicalAlias ?: getString(R.string.space_explore_activity_title)
|
||||||
|
views.toolbar.title = title
|
||||||
|
|
||||||
|
spaceCardRenderer.render(currentParent, emptyList(), this, views.spaceCard)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu) = withState(viewModel) { state ->
|
override fun onPrepareOptionsMenu(menu: Menu) = withState(viewModel) { state ->
|
||||||
@ -96,7 +129,7 @@ class SpaceDirectoryFragment @Inject constructor(
|
|||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.spaceAddRoom -> {
|
R.id.spaceAddRoom -> {
|
||||||
withState(viewModel) { state ->
|
withState(viewModel) { state ->
|
||||||
addExistingRooms(state.spaceId)
|
addExistingRooms(state.spaceId)
|
||||||
}
|
}
|
||||||
@ -138,6 +171,44 @@ class SpaceDirectoryFragment @Inject constructor(
|
|||||||
override fun addExistingRooms(spaceId: String) {
|
override fun addExistingRooms(spaceId: String) {
|
||||||
addExistingRoomActivityResult.launch(SpaceManageActivity.newIntent(requireContext(), spaceId, ManageType.AddRooms))
|
addExistingRoomActivityResult.launch(SpaceManageActivity.newIntent(requireContext(), spaceId, ManageType.AddRooms))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onUrlClicked(url: String, title: String): Boolean {
|
||||||
|
permalinkHandler
|
||||||
|
.launch(requireActivity(), url, null)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe { managed ->
|
||||||
|
if (!managed) {
|
||||||
|
if (title.isValidUrl() && url.isValidUrl() && URL(title).host != URL(url).host) {
|
||||||
|
AlertDialog.Builder(requireActivity())
|
||||||
|
.setTitle(R.string.external_link_confirmation_title)
|
||||||
|
.setMessage(
|
||||||
|
getString(R.string.external_link_confirmation_message, title, url)
|
||||||
|
.toSpannable()
|
||||||
|
.colorizeMatchingText(url, colorProvider.getColorFromAttribute(R.attr.riotx_text_primary_body_contrast))
|
||||||
|
.colorizeMatchingText(title, colorProvider.getColorFromAttribute(R.attr.riotx_text_primary_body_contrast))
|
||||||
|
)
|
||||||
|
.setPositiveButton(R.string._continue) { _, _ ->
|
||||||
|
openUrlInExternalBrowser(requireContext(), url)
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.show()
|
||||||
|
.withColoredButton(DialogInterface.BUTTON_NEGATIVE)
|
||||||
|
} else {
|
||||||
|
// Open in external browser, in a new Tab
|
||||||
|
openUrlInExternalBrowser(requireContext(), url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disposeOnDestroyView()
|
||||||
|
// In fact it is always managed
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUrlLongClicked(url: String): Boolean {
|
||||||
|
// nothing?
|
||||||
|
return false
|
||||||
|
}
|
||||||
// override fun navigateToRoom(roomId: String) {
|
// override fun navigateToRoom(roomId: String) {
|
||||||
// viewModel.handle(SpaceDirectoryViewAction.NavigateToRoom(roomId))
|
// viewModel.handle(SpaceDirectoryViewAction.NavigateToRoom(roomId))
|
||||||
// }
|
// }
|
||||||
|
@ -37,7 +37,9 @@ data class SpaceDirectoryState(
|
|||||||
val joinedRoomsIds: Set<String> = emptySet(),
|
val joinedRoomsIds: Set<String> = emptySet(),
|
||||||
// keys are room alias or roomId
|
// keys are room alias or roomId
|
||||||
val changeMembershipStates: Map<String, ChangeMembershipState> = emptyMap(),
|
val changeMembershipStates: Map<String, ChangeMembershipState> = emptyMap(),
|
||||||
val canAddRooms: Boolean = false
|
val canAddRooms: Boolean = false,
|
||||||
|
// cached room summaries of known rooms
|
||||||
|
val knownRoomSummaries : List<RoomSummary> = emptyList()
|
||||||
) : MvRxState {
|
) : MvRxState {
|
||||||
constructor(args: SpaceDirectoryArgs) : this(
|
constructor(args: SpaceDirectoryArgs) : this(
|
||||||
spaceId = args.spaceId
|
spaceId = args.spaceId
|
||||||
|
@ -66,7 +66,8 @@ class SpaceDirectoryViewModel @AssistedInject constructor(
|
|||||||
val spaceSum = session.getRoomSummary(initialState.spaceId)
|
val spaceSum = session.getRoomSummary(initialState.spaceId)
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
childList = spaceSum?.spaceChildren ?: emptyList()
|
childList = spaceSum?.spaceChildren ?: emptyList(),
|
||||||
|
spaceSummary = spaceSum?.let { Success(spaceSum) } ?: Loading()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,9 +102,14 @@ class SpaceDirectoryViewModel @AssistedInject constructor(
|
|||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val query = session.spaceService().querySpaceChildren(initialState.spaceId)
|
val query = session.spaceService().querySpaceChildren(initialState.spaceId)
|
||||||
|
val knownSummaries = query.second.mapNotNull {
|
||||||
|
session.getRoomSummary(it.childRoomId)
|
||||||
|
?.takeIf { it.membership == Membership.JOIN } // only take if joined because it will be up to date (synced)
|
||||||
|
}
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
spaceSummaryApiResult = Success(query.second)
|
spaceSummaryApiResult = Success(query.second),
|
||||||
|
knownRoomSummaries = knownSummaries
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
@ -148,7 +154,7 @@ class SpaceDirectoryViewModel @AssistedInject constructor(
|
|||||||
copy(hierarchyStack = hierarchyStack + listOf(action.spaceChildInfo.childRoomId))
|
copy(hierarchyStack = hierarchyStack + listOf(action.spaceChildInfo.childRoomId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SpaceDirectoryViewAction.HandleBack -> {
|
SpaceDirectoryViewAction.HandleBack -> {
|
||||||
withState {
|
withState {
|
||||||
if (it.hierarchyStack.isEmpty()) {
|
if (it.hierarchyStack.isEmpty()) {
|
||||||
_viewEvents.post(SpaceDirectoryViewEvents.Dismiss)
|
_viewEvents.post(SpaceDirectoryViewEvents.Dismiss)
|
||||||
@ -161,20 +167,20 @@ class SpaceDirectoryViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is SpaceDirectoryViewAction.JoinOrOpen -> {
|
is SpaceDirectoryViewAction.JoinOrOpen -> {
|
||||||
handleJoinOrOpen(action.spaceChildInfo)
|
handleJoinOrOpen(action.spaceChildInfo)
|
||||||
}
|
}
|
||||||
is SpaceDirectoryViewAction.NavigateToRoom -> {
|
is SpaceDirectoryViewAction.NavigateToRoom -> {
|
||||||
_viewEvents.post(SpaceDirectoryViewEvents.NavigateToRoom(action.roomId))
|
_viewEvents.post(SpaceDirectoryViewEvents.NavigateToRoom(action.roomId))
|
||||||
}
|
}
|
||||||
is SpaceDirectoryViewAction.ShowDetails -> {
|
is SpaceDirectoryViewAction.ShowDetails -> {
|
||||||
// This is temporary for now to at least display something for the space beta
|
// This is temporary for now to at least display something for the space beta
|
||||||
// It's not ideal as it's doing some peeking that is not needed.
|
// It's not ideal as it's doing some peeking that is not needed.
|
||||||
session.permalinkService().createRoomPermalink(action.spaceChildInfo.childRoomId)?.let {
|
session.permalinkService().createRoomPermalink(action.spaceChildInfo.childRoomId)?.let {
|
||||||
_viewEvents.post(SpaceDirectoryViewEvents.NavigateToMxToBottomSheet(it))
|
_viewEvents.post(SpaceDirectoryViewEvents.NavigateToMxToBottomSheet(it))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SpaceDirectoryViewAction.Retry -> {
|
SpaceDirectoryViewAction.Retry -> {
|
||||||
refreshFromApi()
|
refreshFromApi()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ import android.os.Parcelable
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.isGone
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
import com.airbnb.mvrx.Loading
|
import com.airbnb.mvrx.Loading
|
||||||
@ -33,12 +32,12 @@ import com.airbnb.mvrx.fragmentViewModel
|
|||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.di.ScreenComponent
|
import im.vector.app.core.di.ScreenComponent
|
||||||
import im.vector.app.core.extensions.setTextOrHide
|
|
||||||
import im.vector.app.core.platform.ButtonStateView
|
import im.vector.app.core.platform.ButtonStateView
|
||||||
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
||||||
import im.vector.app.core.utils.toast
|
import im.vector.app.core.utils.toast
|
||||||
import im.vector.app.databinding.BottomSheetInvitedToSpaceBinding
|
import im.vector.app.databinding.BottomSheetInvitedToSpaceBinding
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
|
import im.vector.app.features.matrixto.SpaceCardRenderer
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -60,6 +59,9 @@ class SpaceInviteBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetIn
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var avatarRenderer: AvatarRenderer
|
lateinit var avatarRenderer: AvatarRenderer
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var spaceCardRenderer: SpaceCardRenderer
|
||||||
|
|
||||||
private val viewModel: SpaceInviteBottomSheetViewModel by fragmentViewModel(SpaceInviteBottomSheetViewModel::class)
|
private val viewModel: SpaceInviteBottomSheetViewModel by fragmentViewModel(SpaceInviteBottomSheetViewModel::class)
|
||||||
|
|
||||||
@Inject lateinit var viewModelFactory: SpaceInviteBottomSheetViewModel.Factory
|
@Inject lateinit var viewModelFactory: SpaceInviteBottomSheetViewModel.Factory
|
||||||
@ -133,12 +135,7 @@ class SpaceInviteBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetIn
|
|||||||
views.inviterMxid.isVisible = false
|
views.inviterMxid.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
views.spaceCard.matrixToCardContentVisibility.isVisible = true
|
spaceCardRenderer.render(summary, state.peopleYouKnow.invoke().orEmpty(), null, views.spaceCard)
|
||||||
summary?.toMatrixItem()?.let { avatarRenderer.renderSpace(it, views.spaceCard.matrixToCardAvatar) }
|
|
||||||
views.spaceCard.matrixToCardNameText.text = summary?.displayName
|
|
||||||
views.spaceCard.matrixToBetaTag.isVisible = true
|
|
||||||
views.spaceCard.matrixToCardAliasText.setTextOrHide(summary?.canonicalAlias)
|
|
||||||
views.spaceCard.matrixToCardDescText.setTextOrHide(summary?.topic)
|
|
||||||
|
|
||||||
views.spaceCard.matrixToCardMainButton.button.text = getString(R.string.accept)
|
views.spaceCard.matrixToCardMainButton.button.text = getString(R.string.accept)
|
||||||
views.spaceCard.matrixToCardSecondaryButton.button.text = getString(R.string.decline)
|
views.spaceCard.matrixToCardSecondaryButton.button.text = getString(R.string.decline)
|
||||||
@ -178,40 +175,6 @@ class SpaceInviteBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetIn
|
|||||||
views.spaceCard.matrixToCardSecondaryButton.button.isEnabled = true
|
views.spaceCard.matrixToCardSecondaryButton.button.isEnabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val memberCount = summary?.otherMemberIds?.size ?: 0
|
|
||||||
if (memberCount != 0) {
|
|
||||||
views.spaceCard.matrixToMemberPills.isVisible = true
|
|
||||||
views.spaceCard.spaceChildMemberCountText.text = resources.getQuantityString(R.plurals.room_title_members, memberCount, memberCount)
|
|
||||||
} else {
|
|
||||||
// hide the pill
|
|
||||||
views.spaceCard.matrixToMemberPills.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
val peopleYouKnow = state.peopleYouKnow.invoke().orEmpty()
|
|
||||||
|
|
||||||
val images = listOf(
|
|
||||||
views.spaceCard.knownMember1,
|
|
||||||
views.spaceCard.knownMember2,
|
|
||||||
views.spaceCard.knownMember3,
|
|
||||||
views.spaceCard.knownMember4,
|
|
||||||
views.spaceCard.knownMember5
|
|
||||||
).onEach { it.isGone = true }
|
|
||||||
|
|
||||||
if (peopleYouKnow.isEmpty()) {
|
|
||||||
views.spaceCard.peopleYouMayKnowText.isVisible = false
|
|
||||||
} else {
|
|
||||||
peopleYouKnow.forEachIndexed { index, item ->
|
|
||||||
images[index].isVisible = true
|
|
||||||
avatarRenderer.render(item.toMatrixItem(), images[index])
|
|
||||||
}
|
|
||||||
views.spaceCard.peopleYouMayKnowText.setTextOrHide(
|
|
||||||
resources.getQuantityString(R.plurals.space_people_you_know,
|
|
||||||
peopleYouKnow.count(),
|
|
||||||
peopleYouKnow.count()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetInvitedToSpaceBinding {
|
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetInvitedToSpaceBinding {
|
||||||
|
@ -27,7 +27,6 @@ import im.vector.app.features.home.AvatarRenderer
|
|||||||
import im.vector.app.features.home.room.list.RoomCategoryItem_
|
import im.vector.app.features.home.room.list.RoomCategoryItem_
|
||||||
import org.matrix.android.sdk.api.session.room.ResultBoundaries
|
import org.matrix.android.sdk.api.session.room.ResultBoundaries
|
||||||
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.room.model.RoomType
|
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -155,7 +154,6 @@ class AddRoomListController @Inject constructor(
|
|||||||
id(item.roomId)
|
id(item.roomId)
|
||||||
matrixItem(item.toMatrixItem())
|
matrixItem(item.toMatrixItem())
|
||||||
avatarRenderer(host.avatarRenderer)
|
avatarRenderer(host.avatarRenderer)
|
||||||
space(item.roomType == RoomType.SPACE)
|
|
||||||
selected(host.selectedItems[item.roomId] ?: false)
|
selected(host.selectedItems[item.roomId] ?: false)
|
||||||
itemClickListener(DebouncedClickListener({
|
itemClickListener(DebouncedClickListener({
|
||||||
host.listener?.onItemSelected(item)
|
host.listener?.onItemSelected(item)
|
||||||
|
@ -34,18 +34,14 @@ abstract class RoomManageSelectionItem : VectorEpoxyModel<RoomManageSelectionIte
|
|||||||
|
|
||||||
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
|
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
|
||||||
@EpoxyAttribute lateinit var matrixItem: MatrixItem
|
@EpoxyAttribute lateinit var matrixItem: MatrixItem
|
||||||
@EpoxyAttribute var space: Boolean = false
|
|
||||||
@EpoxyAttribute var selected: Boolean = false
|
@EpoxyAttribute var selected: Boolean = false
|
||||||
@EpoxyAttribute var suggested: Boolean = false
|
@EpoxyAttribute var suggested: Boolean = false
|
||||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemClickListener: View.OnClickListener? = null
|
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemClickListener: View.OnClickListener? = null
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
if (space) {
|
avatarRenderer.render(matrixItem, holder.avatarImageView)
|
||||||
avatarRenderer.renderSpace(matrixItem, holder.avatarImageView)
|
|
||||||
} else {
|
|
||||||
avatarRenderer.render(matrixItem, holder.avatarImageView)
|
|
||||||
}
|
|
||||||
holder.titleText.text = matrixItem.getBestName()
|
holder.titleText.text = matrixItem.getBestName()
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
|
@ -33,17 +33,13 @@ abstract class RoomSelectionItem : VectorEpoxyModel<RoomSelectionItem.Holder>()
|
|||||||
|
|
||||||
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
|
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
|
||||||
@EpoxyAttribute lateinit var matrixItem: MatrixItem
|
@EpoxyAttribute lateinit var matrixItem: MatrixItem
|
||||||
@EpoxyAttribute var space: Boolean = false
|
|
||||||
@EpoxyAttribute var selected: Boolean = false
|
@EpoxyAttribute var selected: Boolean = false
|
||||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemClickListener: View.OnClickListener? = null
|
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemClickListener: View.OnClickListener? = null
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
if (space) {
|
avatarRenderer.render(matrixItem, holder.avatarImageView)
|
||||||
avatarRenderer.renderSpace(matrixItem, holder.avatarImageView)
|
|
||||||
} else {
|
|
||||||
avatarRenderer.render(matrixItem, holder.avatarImageView)
|
|
||||||
}
|
|
||||||
holder.titleText.text = matrixItem.getBestName()
|
holder.titleText.text = matrixItem.getBestName()
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
|
@ -27,7 +27,6 @@ import im.vector.app.core.resources.StringProvider
|
|||||||
import im.vector.app.core.ui.list.genericFooterItem
|
import im.vector.app.core.ui.list.genericFooterItem
|
||||||
import im.vector.app.core.utils.DebouncedClickListener
|
import im.vector.app.core.utils.DebouncedClickListener
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -83,7 +82,6 @@ class SpaceManageRoomsController @Inject constructor(
|
|||||||
matrixItem(childInfo.toMatrixItem())
|
matrixItem(childInfo.toMatrixItem())
|
||||||
avatarRenderer(host.avatarRenderer)
|
avatarRenderer(host.avatarRenderer)
|
||||||
suggested(childInfo.suggested ?: false)
|
suggested(childInfo.suggested ?: false)
|
||||||
space(childInfo.roomType == RoomType.SPACE)
|
|
||||||
selected(data.selectedRooms.contains(childInfo.childRoomId))
|
selected(data.selectedRooms.contains(childInfo.childRoomId))
|
||||||
itemClickListener(DebouncedClickListener({
|
itemClickListener(DebouncedClickListener({
|
||||||
host.listener?.toggleSelection(childInfo)
|
host.listener?.toggleSelection(childInfo)
|
||||||
|
@ -71,7 +71,7 @@ class SpaceSettingsController @Inject constructor(
|
|||||||
// Use the current value
|
// Use the current value
|
||||||
avatarRenderer(host.avatarRenderer)
|
avatarRenderer(host.avatarRenderer)
|
||||||
// We do not want to use the fallback avatar url, which can be the other user avatar, or the current user avatar.
|
// We do not want to use the fallback avatar url, which can be the other user avatar, or the current user avatar.
|
||||||
matrixItem(roomSummary.toMatrixItem().copy(avatarUrl = data.currentRoomAvatarUrl))
|
matrixItem(roomSummary.toMatrixItem().updateAvatar(data.currentRoomAvatarUrl))
|
||||||
}
|
}
|
||||||
RoomSettingsViewState.AvatarAction.DeleteAvatar ->
|
RoomSettingsViewState.AvatarAction.DeleteAvatar ->
|
||||||
imageUri(null)
|
imageUri(null)
|
||||||
|
@ -139,7 +139,7 @@ class SpaceSettingsFragment @Inject constructor(
|
|||||||
drawableProvider.getDrawable(R.drawable.ic_beta_pill),
|
drawableProvider.getDrawable(R.drawable.ic_beta_pill),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
avatarRenderer.renderSpace(it.toMatrixItem(), views.roomSettingsToolbarAvatarImageView)
|
avatarRenderer.render(it.toMatrixItem(), views.roomSettingsToolbarAvatarImageView)
|
||||||
views.roomSettingsDecorationToolbarAvatarImageView.render(it.roomEncryptionTrustLevel)
|
views.roomSettingsDecorationToolbarAvatarImageView.render(it.roomEncryptionTrustLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,8 +148,8 @@ class SpacePreviewFragment @Inject constructor(
|
|||||||
// val roomPeekResult = preview.summary.roomPeekResult
|
// val roomPeekResult = preview.summary.roomPeekResult
|
||||||
val spaceName = spacePreviewState.spaceInfo.invoke()?.name ?: spacePreviewState.name ?: ""
|
val spaceName = spacePreviewState.spaceInfo.invoke()?.name ?: spacePreviewState.name ?: ""
|
||||||
val spaceAvatarUrl = spacePreviewState.spaceInfo.invoke()?.avatarUrl ?: spacePreviewState.avatarUrl
|
val spaceAvatarUrl = spacePreviewState.spaceInfo.invoke()?.avatarUrl ?: spacePreviewState.avatarUrl
|
||||||
val mxItem = MatrixItem.RoomItem(spacePreviewState.idOrAlias, spaceName, spaceAvatarUrl)
|
val mxItem = MatrixItem.SpaceItem(spacePreviewState.idOrAlias, spaceName, spaceAvatarUrl)
|
||||||
avatarRenderer.renderSpace(mxItem, views.spacePreviewToolbarAvatar)
|
avatarRenderer.render(mxItem, views.spacePreviewToolbarAvatar)
|
||||||
views.roomPreviewNoPreviewToolbarTitle.text = spaceName
|
views.roomPreviewNoPreviewToolbarTitle.text = spaceName
|
||||||
// }
|
// }
|
||||||
// is SpacePeekResult.SpacePeekError,
|
// is SpacePeekResult.SpacePeekError,
|
||||||
|
@ -48,8 +48,8 @@ abstract class SubSpaceItem : VectorEpoxyModel<SubSpaceItem.Holder>() {
|
|||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
holder.nameText.text = title
|
holder.nameText.text = title
|
||||||
|
|
||||||
avatarRenderer.renderSpace(
|
avatarRenderer.render(
|
||||||
MatrixItem.RoomItem(roomId, title, avatarUrl),
|
MatrixItem.SpaceItem(roomId, title, avatarUrl),
|
||||||
holder.avatarImageView
|
holder.avatarImageView
|
||||||
)
|
)
|
||||||
holder.tabView.tabDepth = depth
|
holder.tabView.tabDepth = depth
|
||||||
|
@ -58,7 +58,7 @@
|
|||||||
android:id="@+id/matrixToCardAliasText"
|
android:id="@+id/matrixToCardAliasText"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="8dp"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:textAlignment="textStart"
|
android:textAlignment="textStart"
|
||||||
@ -70,12 +70,43 @@
|
|||||||
tools:text="@sample/rooms.json/data/alias"
|
tools:text="@sample/rooms.json/data/alias"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/matrixToAccessImage"
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/matrixToAccessText"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/matrixToAccessText"
|
||||||
|
app:tint="?riotx_text_secondary"
|
||||||
|
tools:src="@drawable/ic_public_room"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/matrixToAccessText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:textColor="?riotx_text_secondary"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/matrixToAccessImage"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/matrixToCardAliasText"
|
||||||
|
app:layout_goneMarginTop="0dp"
|
||||||
|
tools:text="Public Space"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/matrixToMemberPills"
|
android:id="@+id/matrixToMemberPills"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:background="@drawable/pill_receipt"
|
android:background="@drawable/pill_receipt"
|
||||||
|
android:backgroundTint="?riotx_reaction_background_off"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingStart="12dp"
|
android:paddingStart="12dp"
|
||||||
@ -85,7 +116,7 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0"
|
app:layout_constraintHorizontal_bias="0"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/matrixToCardAliasText">
|
app:layout_constraintTop_toBottomOf="@id/matrixToAccessText">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/spaceChildMemberCountIcon"
|
android:id="@+id/spaceChildMemberCountIcon"
|
||||||
@ -113,6 +144,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
|
android:autoLink="web"
|
||||||
android:maxLines="4"
|
android:maxLines="4"
|
||||||
android:textAlignment="textStart"
|
android:textAlignment="textStart"
|
||||||
android:textColor="?riotx_text_secondary"
|
android:textColor="?riotx_text_secondary"
|
||||||
|
@ -7,29 +7,56 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?riotx_background">
|
android:background="?riotx_background">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
style="@style/VectorAppBarLayoutStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="wrap_content"
|
||||||
|
android:elevation="4dp">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||||
<androidx.appcompat.widget.Toolbar
|
android:id="@+id/spaceExploreCollapsingToolbarLayout"
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:elevation="4dp"
|
android:theme="@style/Vector.Toolbar.Profile"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:contentScrim="?riotx_background"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:scrimAnimationDuration="250"
|
||||||
|
app:scrimVisibleHeightTrigger="120dp"
|
||||||
|
app:titleEnabled="false"
|
||||||
|
app:toolbarId="@+id/toolbar">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<FrameLayout
|
||||||
android:id="@+id/roomDirectoryPickerList"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="0dp"
|
android:layout_marginTop="40dp">
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
<include
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
android:id="@+id/spaceCard"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/toolbar"
|
layout="@layout/fragment_matrix_to_room_space_card" />
|
||||||
tools:listitem="@layout/item_room_directory" />
|
</FrameLayout>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:elevation="4dp"
|
||||||
|
app:layout_collapseMode="pin"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/roomDirectoryPickerList"
|
||||||
|
android:background="?riotx_background"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
tools:listitem="@layout/item_room_directory" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@ -3267,6 +3267,7 @@
|
|||||||
<string name="a11y_rule_notify_off">Do not notify</string>
|
<string name="a11y_rule_notify_off">Do not notify</string>
|
||||||
<string name="a11y_view_read_receipts">View read receipts</string>
|
<string name="a11y_view_read_receipts">View read receipts</string>
|
||||||
<string name="a11y_public_room">This room is public</string>
|
<string name="a11y_public_room">This room is public</string>
|
||||||
|
<string name="a11y_public_space">This Space is public</string>
|
||||||
|
|
||||||
<string name="dev_tools_menu_name">Dev Tools</string>
|
<string name="dev_tools_menu_name">Dev Tools</string>
|
||||||
<string name="dev_tools_explore_room_state">Explore Room State</string>
|
<string name="dev_tools_explore_room_state">Explore Room State</string>
|
||||||
@ -3298,6 +3299,8 @@
|
|||||||
<string name="event_status_delete_all_failed_dialog_title">Delete unsent messages</string>
|
<string name="event_status_delete_all_failed_dialog_title">Delete unsent messages</string>
|
||||||
<string name="event_status_delete_all_failed_dialog_message">Are you sure you want to delete all unsent messages in this room?</string>
|
<string name="event_status_delete_all_failed_dialog_message">Are you sure you want to delete all unsent messages in this room?</string>
|
||||||
|
|
||||||
|
<string name="public_space">Public space</string>
|
||||||
|
<string name="private_space">Private space</string>
|
||||||
<string name="add_space">Add Space</string>
|
<string name="add_space">Add Space</string>
|
||||||
<string name="your_public_space">Your public space</string>
|
<string name="your_public_space">Your public space</string>
|
||||||
<string name="your_private_space">Your private space</string>
|
<string name="your_private_space">Your private space</string>
|
||||||
@ -3393,4 +3396,5 @@
|
|||||||
<string name="this_space_has_no_rooms_not_admin">Some rooms may be hidden because they’re private and you need an invite.\nYou don’t have permission to add rooms.</string>
|
<string name="this_space_has_no_rooms_not_admin">Some rooms may be hidden because they’re private and you need an invite.\nYou don’t have permission to add rooms.</string>
|
||||||
<string name="this_space_has_no_rooms_admin">Some rooms may be hidden because they’re private and you need an invite.</string>
|
<string name="this_space_has_no_rooms_admin">Some rooms may be hidden because they’re private and you need an invite.</string>
|
||||||
|
|
||||||
|
<string name="unnamed_room">Unnamed Room</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user