Fixes #3386 show space description in explore header
This commit is contained in:
parent
2bea2de0c5
commit
447bd98a78
@ -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
|
||||
|
||||
)
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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 :/
|
||||
|
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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) }
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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))
|
||||
// }
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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"
|
||||
|
@ -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>
|
@ -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 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="unnamed_room">Unnamed Room</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user