Fixes #3386 show space description in explore header

This commit is contained in:
Valere 2021-05-24 10:54:09 +02:00
parent 2bea2de0c5
commit 447bd98a78
17 changed files with 389 additions and 91 deletions

View File

@ -32,5 +32,7 @@ data class SpaceChildInfo(
val parentRoomId: String?,
val suggested: Boolean?,
val canonicalAlias: String?,
val aliases: List<String>?
val aliases: List<String>?,
val worldReadable: Boolean
)

View File

@ -28,7 +28,8 @@ sealed class PeekResult {
val numJoinedMembers: Int?,
val roomType: String?,
val viaServers: List<String>,
val someMembers: List<MatrixItem.UserItem>?
val someMembers: List<MatrixItem.UserItem>?,
val isPublic: Boolean
) : PeekResult()
data class PeekingNotAllowed(

View File

@ -159,4 +159,4 @@ fun RoomMemberSummary.toMatrixItem() = MatrixItem.UserItem(userId, displayName,
fun SenderInfo.toMatrixItem() = MatrixItem.UserItem(userId, disambiguatedDisplayName, avatarUrl)
fun SpaceChildInfo.toMatrixItem() = MatrixItem.RoomItem(childRoomId, name ?: canonicalAlias ?: "", avatarUrl)
fun SpaceChildInfo.toMatrixItem() = MatrixItem.RoomItem(childRoomId, name ?: canonicalAlias, avatarUrl)

View File

@ -16,6 +16,7 @@
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.SpaceChildInfo
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,
suggested = it.suggested,
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()

View File

@ -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.RoomCanonicalAliasContent
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.RoomNameContent
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
@ -105,7 +107,8 @@ internal class DefaultPeekRoomTask @Inject constructor(
numJoinedMembers = publicRepoResult.numJoinedMembers,
viaServers = serverList,
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
.lastOrNull { it.type == EventType.STATE_ROOM_CREATE }
?.content
@ -158,7 +166,8 @@ internal class DefaultPeekRoomTask @Inject constructor(
numJoinedMembers = memberCount,
roomType = roomType,
viaServers = serverList,
someMembers = someMembers
someMembers = someMembers,
isPublic = historyVisibility == RoomHistoryVisibility.WORLD_READABLE
)
} catch (failure: Throwable) {
// Would be M_FORBIDDEN if cannot peek :/

View File

@ -147,7 +147,8 @@ internal class DefaultSpaceService @Inject constructor(
parentRoomId = childStateEv.roomId,
suggested = childStateEvContent.suggested,
canonicalAlias = childSummary.canonicalAlias,
aliases = childSummary.aliases
aliases = childSummary.aliases,
worldReadable = childSummary.worldReadable
)
}
}.orEmpty()

View File

@ -63,7 +63,7 @@ abstract class SpaceChildInfoItem : VectorEpoxyModel<SpaceChildInfoItem.Holder>(
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
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.renderSpace(matrixItem, holder.avatarImageView)
} else {

View File

@ -48,7 +48,8 @@ sealed class RoomInfoResult {
val alias: String?,
val membership: Membership,
val roomType: String?,
val viaServers: List<String>?
val viaServers: List<String>?,
val isPublic: Boolean
) : RoomInfoResult()
data class PartialInfo(

View File

@ -118,11 +118,9 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
session.getRoom(permalinkData.roomIdOrAlias)
}
?.roomSummary()
// don't take if not active, as it could be outdated
?.takeIf { it.membership.isActive() }
// XXX fix that
val forceRefresh = true
if (!forceRefresh && knownRoom != null) {
// don't take if not Join, as it could be outdated
?.takeIf { it.membership == Membership.JOIN }
if (knownRoom != null) {
setState {
copy(
roomPeekResult = Success(
@ -134,7 +132,8 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
alias = knownRoom.canonicalAlias,
membership = knownRoom.membership,
roomType = knownRoom.roomType,
viaServers = null
viaServers = null,
isPublic = knownRoom.isPublic
)
)
)
@ -150,7 +149,8 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
alias = peekResult.alias,
membership = knownRoom?.membership ?: Membership.NONE,
roomType = peekResult.roomType,
viaServers = peekResult.viaServers.takeIf { it.isNotEmpty() } ?: permalinkData.viaParameters
viaServers = peekResult.viaServers.takeIf { it.isNotEmpty() } ?: permalinkData.viaParameters,
isPublic = peekResult.isPublic
).also {
peekResult.someMembers?.let { checkForKnownMembers(it) }
}

View File

@ -81,6 +81,15 @@ class MatrixToRoomSpaceFragment @Inject constructor(
if (peek.roomType == RoomType.SPACE) {
views.matrixToBetaTag.isVisible = true
avatarRenderer.renderSpace(matrixItem, views.matrixToCardAvatar)
if (peek.isPublic) {
views.matrixToAccessText.setTextOrHide(context?.getString(R.string.public_space))
views.matrixToAccessImage.isVisible = true
views.matrixToAccessImage.setImageResource(R.drawable.ic_public_room)
} else {
views.matrixToAccessText.setTextOrHide(context?.getString(R.string.private_space))
views.matrixToAccessImage.isVisible = true
views.matrixToAccessImage.setImageResource(R.drawable.ic_room_private)
}
} else {
views.matrixToBetaTag.isVisible = false
avatarRenderer.render(matrixItem, views.matrixToCardAvatar)

View File

@ -0,0 +1,169 @@
/*
* 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.ColorProvider
import im.vector.app.core.resources.DrawableProvider
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.toMatrixItem
import javax.inject.Inject
class SpaceCardHelper @Inject constructor(
private val avatarRenderer: AvatarRenderer,
private val stringProvider: StringProvider,
private val drawableProvider: DrawableProvider,
private val colorProvider: ColorProvider
) {
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.renderSpace(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
}
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.toMatrixItem(), images[index])
}
inCard.peopleYouMayKnowText.setTextOrHide(
stringProvider.getQuantityString(R.plurals.space_people_you_know,
peopleYouKnow.count(),
peopleYouKnow.count()
)
)
}
}
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.renderSpace(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
}
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.toMatrixItem(), images[index])
}
inCard.peopleYouMayKnowText.setTextOrHide(
stringProvider.getQuantityString(R.plurals.space_people_you_know,
peopleYouKnow.count(),
peopleYouKnow.count()
)
)
}
}
}
}

View File

@ -16,6 +16,7 @@
package im.vector.app.features.spaces.explore
import android.content.DialogInterface
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
@ -23,19 +24,33 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
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.withState
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.configureWith
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.OnBackPressed
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.features.home.room.detail.timeline.TimelineEventController
import im.vector.app.features.matrixto.SpaceCardHelper
import im.vector.app.features.permalink.PermalinkHandler
import im.vector.app.features.spaces.manage.ManageType
import im.vector.app.features.spaces.manage.SpaceManageActivity
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
import java.net.URL
import javax.inject.Inject
@Parcelize
@ -44,9 +59,13 @@ data class SpaceDirectoryArgs(
) : Parcelable
class SpaceDirectoryFragment @Inject constructor(
private val epoxyController: SpaceDirectoryController
private val epoxyController: SpaceDirectoryController,
private val permalinkHandler: PermalinkHandler,
private val spaceCardHelper: SpaceCardHelper,
private val colorProvider: ColorProvider
) : VectorBaseFragment<FragmentRoomDirectoryPickerBinding>(),
SpaceDirectoryController.InteractionListener,
TimelineEventController.UrlClickCallback,
OnBackPressed {
override fun getMenuRes() = R.menu.menu_space_directory
@ -71,6 +90,15 @@ class SpaceDirectoryFragment @Inject constructor(
viewModel.selectSubscribe(this, SpaceDirectoryState::canAddRooms) {
invalidateOptionsMenu()
}
views.spaceCard.matrixToCardMainButton.isVisible = false
views.spaceCard.matrixToCardSecondaryButton.isVisible = false
views.spaceCard.knownMember1.isVisible = false
views.spaceCard.knownMember2.isVisible = false
views.spaceCard.knownMember3.isVisible = false
views.spaceCard.knownMember4.isVisible = false
views.spaceCard.knownMember5.isVisible = false
views.spaceCard.peopleYouMayKnowText.isVisible = false
}
override fun onDestroyView() {
@ -82,10 +110,21 @@ class SpaceDirectoryFragment @Inject constructor(
override fun invalidate() = withState(viewModel) { 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 }
}?.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
spaceCardHelper.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
spaceCardHelper.render(currentParent, emptyList(), this, views.spaceCard)
}
}
override fun onPrepareOptionsMenu(menu: Menu) = withState(viewModel) { state ->
@ -96,7 +135,7 @@ class SpaceDirectoryFragment @Inject constructor(
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.spaceAddRoom -> {
R.id.spaceAddRoom -> {
withState(viewModel) { state ->
addExistingRooms(state.spaceId)
}
@ -138,6 +177,44 @@ class SpaceDirectoryFragment @Inject constructor(
override fun addExistingRooms(spaceId: String) {
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) {
// viewModel.handle(SpaceDirectoryViewAction.NavigateToRoom(roomId))
// }

View File

@ -66,7 +66,8 @@ class SpaceDirectoryViewModel @AssistedInject constructor(
val spaceSum = session.getRoomSummary(initialState.spaceId)
setState {
copy(
childList = spaceSum?.spaceChildren ?: emptyList()
childList = spaceSum?.spaceChildren ?: emptyList(),
spaceSummary = spaceSum?.let { Success(spaceSum) } ?: Loading()
)
}
@ -148,7 +149,7 @@ class SpaceDirectoryViewModel @AssistedInject constructor(
copy(hierarchyStack = hierarchyStack + listOf(action.spaceChildInfo.childRoomId))
}
}
SpaceDirectoryViewAction.HandleBack -> {
SpaceDirectoryViewAction.HandleBack -> {
withState {
if (it.hierarchyStack.isEmpty()) {
_viewEvents.post(SpaceDirectoryViewEvents.Dismiss)
@ -161,20 +162,20 @@ class SpaceDirectoryViewModel @AssistedInject constructor(
}
}
}
is SpaceDirectoryViewAction.JoinOrOpen -> {
is SpaceDirectoryViewAction.JoinOrOpen -> {
handleJoinOrOpen(action.spaceChildInfo)
}
is SpaceDirectoryViewAction.NavigateToRoom -> {
is SpaceDirectoryViewAction.NavigateToRoom -> {
_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
// It's not ideal as it's doing some peeking that is not needed.
session.permalinkService().createRoomPermalink(action.spaceChildInfo.childRoomId)?.let {
_viewEvents.post(SpaceDirectoryViewEvents.NavigateToMxToBottomSheet(it))
}
}
SpaceDirectoryViewAction.Retry -> {
SpaceDirectoryViewAction.Retry -> {
refreshFromApi()
}
}

View File

@ -22,7 +22,6 @@ import android.os.Parcelable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
@ -33,12 +32,12 @@ import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import im.vector.app.R
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.VectorBaseBottomSheetDialogFragment
import im.vector.app.core.utils.toast
import im.vector.app.databinding.BottomSheetInvitedToSpaceBinding
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.matrixto.SpaceCardHelper
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.util.toMatrixItem
import javax.inject.Inject
@ -60,6 +59,9 @@ class SpaceInviteBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetIn
@Inject
lateinit var avatarRenderer: AvatarRenderer
@Inject
lateinit var spaceCardHelper: SpaceCardHelper
private val viewModel: SpaceInviteBottomSheetViewModel by fragmentViewModel(SpaceInviteBottomSheetViewModel::class)
@Inject lateinit var viewModelFactory: SpaceInviteBottomSheetViewModel.Factory
@ -133,12 +135,7 @@ class SpaceInviteBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetIn
views.inviterMxid.isVisible = false
}
views.spaceCard.matrixToCardContentVisibility.isVisible = true
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)
spaceCardHelper.render(summary, state.peopleYouKnow.invoke().orEmpty(), null, views.spaceCard)
views.spaceCard.matrixToCardMainButton.button.text = getString(R.string.accept)
views.spaceCard.matrixToCardSecondaryButton.button.text = getString(R.string.decline)
@ -178,40 +175,6 @@ class SpaceInviteBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetIn
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 {

View File

@ -58,7 +58,7 @@
android:id="@+id/matrixToCardAliasText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginTop="8dp"
android:maxLines="1"
android:singleLine="true"
android:textAlignment="textStart"
@ -70,12 +70,43 @@
tools:text="@sample/rooms.json/data/alias"
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
android:id="@+id/matrixToMemberPills"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@drawable/pill_receipt"
android:backgroundTint="?riotx_reaction_background_off"
android:gravity="center"
android:orientation="horizontal"
android:paddingStart="12dp"
@ -85,7 +116,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/matrixToCardAliasText">
app:layout_constraintTop_toBottomOf="@id/matrixToAccessText">
<ImageView
android:id="@+id/spaceChildMemberCountIcon"
@ -113,6 +144,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:autoLink="web"
android:maxLines="4"
android:textAlignment="textStart"
android:textColor="?riotx_text_secondary"

View File

@ -7,29 +7,56 @@
android:layout_height="match_parent"
android:background="?riotx_background">
<androidx.constraintlayout.widget.ConstraintLayout
<com.google.android.material.appbar.AppBarLayout
style="@style/VectorAppBarLayoutStyle"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content"
android:elevation="4dp">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/spaceExploreCollapsingToolbarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
android:layout_height="match_parent"
android:theme="@style/Vector.Toolbar.Profile"
app:contentScrim="?riotx_background"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:scrimAnimationDuration="250"
app:scrimVisibleHeightTrigger="120dp"
app:titleEnabled="false"
app:toolbarId="@+id/toolbar">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/roomDirectoryPickerList"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar"
tools:listitem="@layout/item_room_directory" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp">
<include
android:id="@+id/spaceCard"
layout="@layout/fragment_matrix_to_room_space_card" />
</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>

View File

@ -3262,6 +3262,7 @@
<string name="a11y_rule_notify_off">Do not notify</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_space">This Space is public</string>
<string name="dev_tools_menu_name">Dev Tools</string>
<string name="dev_tools_explore_room_state">Explore Room State</string>
@ -3293,6 +3294,8 @@
<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="public_space">Public space</string>
<string name="private_space">Private space</string>
<string name="add_space">Add Space</string>
<string name="your_public_space">Your public space</string>
<string name="your_private_space">Your private space</string>
@ -3388,4 +3391,5 @@
<string name="this_space_has_no_rooms_not_admin">Some rooms may be hidden because theyre private and you need an invite.\nYou dont have permission to add rooms.</string>
<string name="this_space_has_no_rooms_admin">Some rooms may be hidden because theyre private and you need an invite.</string>
<string name="unnamed_room">Unnamed Room</string>
</resources>