Invite bottom sheet + fixes + beta tag

This commit is contained in:
Valere 2021-04-30 11:59:10 +02:00
parent c9abdb5def
commit b9b3832ee3
19 changed files with 617 additions and 229 deletions

View file

@ -24,6 +24,7 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.utils.BehaviorDataSource
import im.vector.app.features.ui.UiStateRepository
import io.reactivex.disposables.CompositeDisposable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.tryOrNull
@ -68,7 +69,7 @@ class AppStateHandler @Inject constructor(
val spaceSum = spaceId?.let { uSession?.getRoomSummary(spaceId) }
selectedSpaceDataSource.post(Option.just(RoomGroupingMethod.BySpace(spaceSum)))
if (spaceId != null) {
GlobalScope.launch {
GlobalScope.launch(Dispatchers.IO) {
tryOrNull {
uSession?.getRoom(spaceId)?.loadRoomMembersIfNeeded()
}

View file

@ -81,6 +81,7 @@ import im.vector.app.features.spaces.InviteRoomSpaceChooserBottomSheet
import im.vector.app.features.spaces.ShareSpaceBottomSheet
import im.vector.app.features.spaces.SpaceCreationActivity
import im.vector.app.features.spaces.SpaceExploreActivity
import im.vector.app.features.spaces.SpaceInviteBottomSheet
import im.vector.app.features.spaces.SpaceSettingsMenuBottomSheet
import im.vector.app.features.spaces.manage.SpaceManageActivity
import im.vector.app.features.terms.ReviewTermsActivity
@ -185,6 +186,7 @@ interface ScreenComponent {
fun inject(bottomSheet: ShareSpaceBottomSheet)
fun inject(bottomSheet: SpaceSettingsMenuBottomSheet)
fun inject(bottomSheet: InviteRoomSpaceChooserBottomSheet)
fun inject(bottomSheet: SpaceInviteBottomSheet)
/* ==========================================================================================
* Others

View file

@ -60,6 +60,7 @@ import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.settings.VectorSettingsActivity
import im.vector.app.features.spaces.ShareSpaceBottomSheet
import im.vector.app.features.spaces.SpaceCreationActivity
import im.vector.app.features.spaces.SpaceInviteBottomSheet
import im.vector.app.features.spaces.SpacePreviewActivity
import im.vector.app.features.spaces.SpaceSettingsMenuBottomSheet
import im.vector.app.features.themes.ThemeUtils
@ -210,6 +211,18 @@ class HomeActivity :
})
.show(supportFragmentManager, "SPACE_SETTINGS")
}
is HomeActivitySharedAction.OpenSpaceInvite -> {
SpaceInviteBottomSheet.newInstance(sharedAction.spaceId, object : SpaceInviteBottomSheet.InteractionListener {
override fun onAccept(spaceId: String) {
navigator.switchToSpace(this@HomeActivity, spaceId, Navigator.PostSwitchSpaceAction.None)
}
override fun onDecline(spaceId: String) {
// nop
}
})
.show(supportFragmentManager, "SPACE_INVITE")
}
}.exhaustive
}
.disposeOnDestroy()

View file

@ -27,5 +27,6 @@ sealed class HomeActivitySharedAction : VectorSharedAction {
data class OpenGroup(val clearFragment: Boolean) : HomeActivitySharedAction()
object AddSpace : HomeActivitySharedAction()
data class OpenSpacePreview(val spaceId: String) : HomeActivitySharedAction()
data class OpenSpaceInvite(val spaceId: String) : HomeActivitySharedAction()
data class ShowSpaceSettings(val spaceId: String) : HomeActivitySharedAction()
}

View file

@ -20,6 +20,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import com.airbnb.mvrx.Fail
@ -71,8 +72,10 @@ class MatrixToRoomSpaceFragment @Inject constructor(
is RoomInfoResult.FullInfo -> {
val matrixItem = peek.roomItem
if (peek.roomType == RoomType.SPACE) {
views.matrixToBetaTag.isVisible = true
avatarRenderer.renderSpace(matrixItem, views.matrixToCardAvatar)
} else {
views.matrixToBetaTag.isVisible = false
avatarRenderer.render(matrixItem, views.matrixToCardAvatar)
}
views.matrixToCardNameText.setTextOrHide(peek.name)
@ -97,19 +100,19 @@ class MatrixToRoomSpaceFragment @Inject constructor(
Membership.LEAVE,
Membership.NONE -> {
views.matrixToCardMainButton.isVisible = true
views.matrixToCardMainButton.text = getString(joinTextRes)
views.matrixToCardMainButton.button.text = getString(joinTextRes)
views.matrixToCardSecondaryButton.isVisible = false
}
Membership.INVITE -> {
views.matrixToCardMainButton.isVisible = true
views.matrixToCardSecondaryButton.isVisible = true
views.matrixToCardMainButton.text = getString(joinTextRes)
views.matrixToCardSecondaryButton.text = getString(R.string.decline)
views.matrixToCardMainButton.button.text = getString(joinTextRes)
views.matrixToCardSecondaryButton.button.text = getString(R.string.decline)
}
Membership.JOIN -> {
views.matrixToCardMainButton.isVisible = true
views.matrixToCardSecondaryButton.isVisible = false
views.matrixToCardMainButton.text = getString(R.string.action_open)
views.matrixToCardMainButton.button.text = getString(R.string.action_open)
}
Membership.KNOCK,
Membership.BAN -> {
@ -126,7 +129,7 @@ class MatrixToRoomSpaceFragment @Inject constructor(
views.matrixToMemberPills.isVisible = false
views.matrixToCardDescText.setTextOrHide(getString(R.string.room_preview_no_preview))
views.matrixToCardMainButton.text = getString(R.string.join_anyway)
views.matrixToCardMainButton.button.text = getString(R.string.join_anyway)
views.matrixToCardSecondaryButton.isVisible = false
}
RoomInfoResult.NotFound -> {
@ -156,12 +159,10 @@ class MatrixToRoomSpaceFragment @Inject constructor(
}
}
val images = listOf(views.knownMember1, views.knownMember2, views.knownMember3, views.knownMember4, views.knownMember5)
.onEach { it.isGone = true }
when (state.peopleYouKnow) {
is Success -> {
views.matrixToCardPeopleYouKnowVisibility.isVisible = true
val images = listOf(views.knownMember1, views.knownMember2, views.knownMember3, views.knownMember4, views.knownMember5)
.onEach { it.isVisible = false }
val someYouKnow = state.peopleYouKnow.invoke()
someYouKnow.forEachIndexed { index, item ->
images[index].isVisible = true
@ -175,7 +176,7 @@ class MatrixToRoomSpaceFragment @Inject constructor(
)
}
else -> {
views.matrixToCardPeopleYouKnowVisibility.isVisible = false
views.peopleYouMayKnowText.isVisible = false
}
}

View file

@ -0,0 +1,231 @@
/*
* 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.spaces
import android.os.Bundle
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.args
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.error.ErrorFormatter
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 kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.util.toMatrixItem
import javax.inject.Inject
class SpaceInviteBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetInvitedToSpaceBinding>() {
interface InteractionListener {
fun onAccept(spaceId: String)
fun onDecline(spaceId: String)
}
var interactionListener: InteractionListener? = null
@Parcelize
data class Args(
val spaceId: String
) : Parcelable
@Inject
lateinit var activeSessionHolder: ActiveSessionHolder
@Inject
lateinit var avatarRenderer: AvatarRenderer
@Inject
lateinit var errorFormatter: ErrorFormatter
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
override val showExpanded = true
private val inviteArgs: Args by args()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val session = activeSessionHolder.getSafeActiveSession() ?: return
val summary = session.getRoomSummary(inviteArgs.spaceId) ?: return Unit.also {
dismiss()
}
val inviter = summary.inviterId?.let { session.getUser(it) }
if (inviter != null) {
views.inviterAvatarImage.isVisible = true
views.inviterText.isVisible = true
views.inviterMxid.isVisible = true
avatarRenderer.render(inviter.toMatrixItem(), views.inviterAvatarImage)
views.inviterText.text = getString(R.string.user_invites_you, inviter.getBestName())
views.inviterMxid.text = inviter.userId
} else {
views.inviterAvatarImage.isVisible = false
views.inviterText.isVisible = false
views.inviterMxid.isVisible = false
}
views.spaceCard.matrixToCardContentVisibility.isVisible = true
avatarRenderer.renderSpace(summary.toMatrixItem(), 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.render(ButtonStateView.State.Button)
views.spaceCard.matrixToCardMainButton.button.text = getString(R.string.accept)
views.spaceCard.matrixToCardMainButton.callback = object : ButtonStateView.Callback {
override fun onButtonClicked() {
doJoin()
}
override fun onRetryClicked() {
doJoin()
}
private fun doJoin() {
views.spaceCard.matrixToCardMainButton.render(ButtonStateView.State.Loading)
views.spaceCard.matrixToCardSecondaryButton.button.isEnabled = false
GlobalScope.launch(Dispatchers.IO) {
try {
activeSessionHolder.getSafeActiveSession()?.getRoom(inviteArgs.spaceId)?.join()
withContext(Dispatchers.Main) {
if (!isAdded) return@withContext
views.spaceCard.matrixToCardMainButton.render(ButtonStateView.State.Loaded)
views.spaceCard.matrixToCardSecondaryButton.isEnabled = true
interactionListener?.onAccept(inviteArgs.spaceId)
dismiss()
}
} catch (failure: Throwable) {
withContext(Dispatchers.Main) {
if (!isAdded) return@withContext
requireActivity().toast(errorFormatter.toHumanReadable(failure))
views.spaceCard.matrixToCardMainButton.render(ButtonStateView.State.Error)
views.spaceCard.matrixToCardSecondaryButton.button.isEnabled = true
}
}
}
}
}
views.spaceCard.matrixToCardSecondaryButton.render(ButtonStateView.State.Button)
views.spaceCard.matrixToCardSecondaryButton.button.text = getString(R.string.reject)
views.spaceCard.matrixToCardSecondaryButton.callback = object : ButtonStateView.Callback {
override fun onButtonClicked() {
doJoin()
}
override fun onRetryClicked() {
doJoin()
}
private fun doJoin() {
views.spaceCard.matrixToCardSecondaryButton.render(ButtonStateView.State.Loading)
views.spaceCard.matrixToCardSecondaryButton.button.isEnabled = false
GlobalScope.launch(Dispatchers.IO) {
try {
activeSessionHolder.getSafeActiveSession()?.getRoom(inviteArgs.spaceId)?.leave()
withContext(Dispatchers.Main) {
if (!isAdded) return@withContext
views.spaceCard.matrixToCardSecondaryButton.render(ButtonStateView.State.Loaded)
views.spaceCard.matrixToCardMainButton.button.isEnabled = true
interactionListener?.onDecline(inviteArgs.spaceId)
dismiss()
}
} catch (failure: Throwable) {
withContext(Dispatchers.Main) {
if (!isAdded) return@withContext
requireActivity().toast(errorFormatter.toHumanReadable(failure))
views.spaceCard.matrixToCardSecondaryButton.render(ButtonStateView.State.Error)
views.spaceCard.matrixToCardMainButton.button.isEnabled = true
}
}
}
}
}
val memberCount = summary.otherMemberIds.size
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 knownMembers = summary.otherMemberIds.filter {
session.getExistingDirectRoomWithUser(it) != null
}.mapNotNull { session.getUser(it) }
// put one with avatar first, and take 5
val peopleYouKnow = (knownMembers.filter { it.avatarUrl != null } + knownMembers.filter { it.avatarUrl == null })
.take(5)
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 {
return BottomSheetInvitedToSpaceBinding.inflate(inflater, container, false)
}
companion object {
fun newInstance(spaceId: String, interactionListener: InteractionListener)
: SpaceInviteBottomSheet {
return SpaceInviteBottomSheet().apply {
this.interactionListener = interactionListener
setArguments(Args(spaceId))
}
}
}
}

View file

@ -60,6 +60,7 @@ class SpaceListFragment @Inject constructor(
is SpaceListViewEvents.OpenSpace -> sharedActionViewModel.post(HomeActivitySharedAction.OpenGroup(it.groupingMethodHasChanged))
is SpaceListViewEvents.AddSpace -> sharedActionViewModel.post(HomeActivitySharedAction.AddSpace)
is SpaceListViewEvents.OpenGroup -> sharedActionViewModel.post(HomeActivitySharedAction.OpenGroup(it.groupingMethodHasChanged))
is SpaceListViewEvents.OpenSpaceInvite -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpaceInvite(it.id))
}.exhaustive
}
}

View file

@ -24,6 +24,7 @@ import im.vector.app.core.platform.VectorViewEvents
sealed class SpaceListViewEvents : VectorViewEvents {
data class OpenSpace(val groupingMethodHasChanged: Boolean) : SpaceListViewEvents()
data class OpenSpaceSummary(val id: String) : SpaceListViewEvents()
data class OpenSpaceInvite(val id: String) : SpaceListViewEvents()
object AddSpace : SpaceListViewEvents()
data class OpenGroup(val groupingMethodHasChanged: Boolean) : SpaceListViewEvents()
}

View file

@ -181,7 +181,7 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp
}
private fun handleSelectSpaceInvite(action: SpaceListAction.OpenSpaceInvite) {
_viewEvents.post(SpaceListViewEvents.OpenSpaceSummary(action.spaceSummary.roomId))
_viewEvents.post(SpaceListViewEvents.OpenSpaceInvite(action.spaceSummary.roomId))
}
private fun handleToggleExpand(action: SpaceListAction.ToggleExpand) = withState { state ->

View file

@ -37,16 +37,15 @@ class SpacePreviewController @Inject constructor(
var interactionListener: InteractionListener? = null
override fun buildModels(data: SpacePreviewState?) {
val result = data?.childInfoList?.invoke() ?: return
val memberCount = data.spaceInfo.invoke()?.memberCount ?: 0
val memberCount = data?.spaceInfo?.invoke()?.memberCount ?: 0
spaceTopSummaryItem {
id("info")
formattedMemberCount(stringProvider.getQuantityString(R.plurals.room_title_members, memberCount, memberCount))
topic(data.spaceInfo.invoke()?.topic ?: data.topic ?: "")
topic(data?.spaceInfo?.invoke()?.topic ?: data?.topic ?: "")
}
val result = data?.childInfoList?.invoke() ?: return
if (result.isNotEmpty()) {
genericItemHeader {
id("header_rooms")

View file

@ -119,14 +119,17 @@ class SpacePreviewFragment @Inject constructor(
}
}
updateToolbar(it)
when (it.inviteTermination) {
is Loading -> sharedActionViewModel.post(SpacePreviewSharedAction.ShowModalLoading)
else -> sharedActionViewModel.post(SpacePreviewSharedAction.HideModalLoading)
}
}
private fun handleViewEvents(viewEvents: SpacePreviewViewEvents) {
when (viewEvents) {
SpacePreviewViewEvents.Dismiss -> {
}
SpacePreviewViewEvents.StartJoining -> {
sharedActionViewModel.post(SpacePreviewSharedAction.ShowModalLoading)
sharedActionViewModel.post(SpacePreviewSharedAction.DismissAction)
}
SpacePreviewViewEvents.JoinSuccess -> {
sharedActionViewModel.post(SpacePreviewSharedAction.HideModalLoading)

View file

@ -26,7 +26,8 @@ data class SpacePreviewState(
val topic: String? = null,
val avatarUrl: String? = null,
val spaceInfo: Async<ChildInfo> = Uninitialized,
val childInfoList: Async<List<ChildInfo>> = Uninitialized
val childInfoList: Async<List<ChildInfo>> = Uninitialized,
val inviteTermination: Async<Unit> = Uninitialized
) : MvRxState {
constructor(args: SpacePreviewArgs) : this(idOrAlias = args.idOrAlias)
}

View file

@ -20,7 +20,6 @@ import im.vector.app.core.platform.VectorViewEvents
sealed class SpacePreviewViewEvents : VectorViewEvents {
object Dismiss: SpacePreviewViewEvents()
object StartJoining: SpacePreviewViewEvents()
object JoinSuccess: SpacePreviewViewEvents()
data class JoinFailure(val message: String?): SpacePreviewViewEvents()
}

View file

@ -28,6 +28,7 @@ import com.airbnb.mvrx.ViewModelContext
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.platform.VectorViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -41,6 +42,7 @@ import timber.log.Timber
class SpacePreviewViewModel @AssistedInject constructor(
@Assisted private val initialState: SpacePreviewState,
private val errorFormatter: ErrorFormatter,
private val session: Session
) : VectorViewModel<SpacePreviewState, SpacePreviewViewAction, SpacePreviewViewEvents>(initialState) {
@ -80,12 +82,15 @@ class SpacePreviewViewModel @AssistedInject constructor(
private fun handleDismissInvite() {
// Here we need to join the space himself as well as the default rooms in that space
// TODO modal loading
setState { copy(inviteTermination = Loading()) }
viewModelScope.launch(Dispatchers.IO) {
try {
session.spaceService().rejectInvite(initialState.idOrAlias, null)
setState { copy(inviteTermination = Uninitialized) }
} catch (failure: Throwable) {
setState { copy(inviteTermination = Uninitialized) }
Timber.e(failure, "## Space: Failed to reject invite")
_viewEvents.post(SpacePreviewViewEvents.JoinFailure(errorFormatter.toHumanReadable(failure)))
}
}
}
@ -98,18 +103,24 @@ class SpacePreviewViewModel @AssistedInject constructor(
val spaceVia = spaceInfo?.viaServers ?: emptyList()
// trigger modal loading
_viewEvents.post(SpacePreviewViewEvents.StartJoining)
setState { copy(inviteTermination = Loading()) }
viewModelScope.launch(Dispatchers.IO) {
val joinResult = session.spaceService().joinSpace(initialState.idOrAlias, null, spaceVia)
when (joinResult) {
JoinSpaceResult.Success,
is JoinSpaceResult.PartialSuccess -> {
// For now we don't handle partial success, it's just success
_viewEvents.post(SpacePreviewViewEvents.JoinSuccess)
}
is JoinSpaceResult.Fail -> {
_viewEvents.post(SpacePreviewViewEvents.JoinFailure(joinResult.error.toString()))
try {
val joinResult = session.spaceService().joinSpace(initialState.idOrAlias, null, spaceVia)
setState { copy(inviteTermination = Uninitialized) }
when (joinResult) {
JoinSpaceResult.Success,
is JoinSpaceResult.PartialSuccess -> {
// For now we don't handle partial success, it's just success
_viewEvents.post(SpacePreviewViewEvents.JoinSuccess)
}
is JoinSpaceResult.Fail -> {
_viewEvents.post(SpacePreviewViewEvents.JoinFailure(joinResult.error.toString()))
}
}
} catch (failure: Throwable) {
// should not throw
Timber.w(failure, "## Failed to join space")
}
}
}
@ -221,7 +232,21 @@ class SpacePreviewViewModel @AssistedInject constructor(
}
} catch (failure: Throwable) {
setState {
copy(spaceInfo = Fail(failure), childInfoList = Fail(failure))
copy(
spaceInfo = session.getRoomSummary(initialState.idOrAlias)?.let {
Success(
ChildInfo(
roomId = it.roomId,
avatarUrl = it.avatarUrl,
name = it.displayName,
topic = it.topic,
memberCount = it.joinedMembersCount,
isSubSpace = false,
viaServers = null,
children = Uninitialized
)
)
} ?: Fail(failure), childInfoList = Fail(failure))
}
}
}

View file

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/bottomSheetScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:background="?riotx_bottom_sheet_background"
android:fadeScrollbars="false"
android:scrollbars="vertical">
<!-- Inviter info-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:padding="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/inviterAvatarImage"
android:layout_width="40dp"
android:layout_height="40dp"
android:contentDescription="@string/avatar"
android:transitionName="profile"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@tools:sample/avatars" />
<TextView
android:id="@+id/inviterText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textColor="?riotx_text_primary"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/inviterAvatarImage"
app:layout_constraintTop_toTopOf="@id/inviterAvatarImage"
tools:text="@string/user_invites_you" />
<TextView
android:id="@+id/inviterMxid"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?riotx_text_secondary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/inviterAvatarImage"
app:layout_constraintTop_toBottomOf="@id/inviterText"
tools:text="@sample/matrix.json/data/mxid" />
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/vctr_list_divider_color" />
<include
android:id="@+id/spaceCard"
layout="@layout/fragment_matrix_to_room_space_card" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View file

@ -1,224 +1,257 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="200dp"
android:padding="16dp">
android:layout_height="wrap_content">
<ImageView
android:id="@+id/matrixToCardAvatar"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginTop="@dimen/layout_vertical_margin_big"
android:contentDescription="@string/avatar"
android:elevation="4dp"
android:transitionName="profile"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@tools:sample/avatars" />
<TextView
android:id="@+id/matrixToCardNameText"
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/matrixToCardContentVisibility"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_vertical_margin"
android:maxLines="1"
android:singleLine="true"
android:textAlignment="textStart"
android:textColor="?riotx_text_primary"
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@+id/matrixToCardAvatar"
tools:text="@sample/matrix.json/data/roomName" />
<TextView
android:id="@+id/matrixToCardAliasText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:maxLines="1"
android:singleLine="true"
android:textAlignment="textStart"
android:textColor="?riotx_text_secondary"
android:textSize="15sp"
android:minHeight="200dp"
android:padding="16dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/matrixToCardNameText"
app:layout_goneMarginTop="0dp"
tools:text="@sample/matrix.json/data/roomAlias" />
<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:gravity="center"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingTop="8dp"
android:paddingEnd="12dp"
android:paddingBottom="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/matrixToCardAliasText">
tools:visibility="visible">
<ImageView
android:id="@+id/spaceChildMemberCountIcon"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="4dp"
android:importantForAccessibility="no"
android:src="@drawable/ic_room_profile_member_list"
app:tint="?riotx_text_primary"
tools:ignore="MissingPrefix" />
android:id="@+id/matrixToCardAvatar"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginTop="20dp"
android:contentDescription="@string/avatar"
android:elevation="4dp"
android:transitionName="profile"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@tools:sample/avatars" />
<TextView
android:id="@+id/spaceChildMemberCountText"
<ImageView
android:id="@+id/matrixToBetaTag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginTop="@dimen/layout_vertical_margin_big"
android:importantForAccessibility="no"
android:src="@drawable/ic_beta_pill"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<TextView
android:id="@+id/matrixToCardNameText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_vertical_margin"
android:maxLines="1"
android:singleLine="true"
android:textAlignment="textStart"
android:textColor="?riotx_text_primary"
tools:text="123 members" />
</LinearLayout>
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@+id/matrixToCardAvatar"
tools:text="@sample/matrix.json/data/roomName" />
<TextView
android:id="@+id/matrixToCardDescText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:maxLines="4"
android:textAlignment="textStart"
android:textColor="?riotx_text_secondary"
android:textSize="15sp"
app:layout_constraintTop_toBottomOf="@id/matrixToMemberPills"
tools:text="@sample/matrix.json/data/roomTopic" />
<TextView
android:id="@+id/matrixToCardAliasText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:maxLines="1"
android:singleLine="true"
android:textAlignment="textStart"
android:textColor="?riotx_text_secondary"
android:textSize="15sp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/matrixToCardNameText"
app:layout_goneMarginTop="0dp"
tools:text="@sample/matrix.json/data/roomAlias" />
<ImageView
android:id="@+id/knownMember5"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@string/avatar"
app:layout_constraintCircle="@id/knownMember4"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="20dp"
tools:ignore="MissingConstraints"
tools:src="@tools:sample/avatars" />
<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:gravity="center"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingTop="8dp"
android:paddingEnd="12dp"
android:paddingBottom="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/matrixToCardAliasText">
<ImageView
android:id="@+id/knownMember4"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@string/avatar"
app:layout_constraintCircle="@id/knownMember3"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="20dp"
tools:ignore="MissingConstraints"
tools:src="@tools:sample/avatars" />
<ImageView
android:id="@+id/spaceChildMemberCountIcon"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="4dp"
android:importantForAccessibility="no"
android:src="@drawable/ic_room_profile_member_list"
app:tint="?riotx_text_primary"
tools:ignore="MissingPrefix" />
<ImageView
android:id="@+id/knownMember3"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@string/avatar"
app:layout_constraintCircle="@id/knownMember2"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="20dp"
tools:ignore="MissingConstraints"
tools:src="@tools:sample/avatars" />
<TextView
android:id="@+id/spaceChildMemberCountText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:textColor="?riotx_text_primary"
tools:text="123 members" />
</LinearLayout>
<ImageView
android:id="@+id/knownMember2"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@string/avatar"
app:layout_constraintCircle="@id/knownMember1"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="20dp"
tools:ignore="MissingConstraints"
tools:src="@tools:sample/avatars" />
<TextView
android:id="@+id/matrixToCardDescText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:maxLines="4"
android:textAlignment="textStart"
android:textColor="?riotx_text_secondary"
android:textSize="15sp"
app:layout_constraintTop_toBottomOf="@id/matrixToMemberPills"
tools:text="@sample/matrix.json/data/roomTopic" />
<ImageView
android:id="@+id/knownMember1"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="8dp"
android:contentDescription="@string/avatar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/matrixToCardDescText"
tools:src="@tools:sample/avatars" />
<ImageView
android:id="@+id/knownMember5"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@string/avatar"
app:layout_constraintCircle="@id/knownMember4"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="20dp"
tools:ignore="MissingConstraints"
tools:src="@tools:sample/avatars"
tools:visibility="gone" />
<TextView
android:id="@+id/peopleYouMayKnowText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:textColor="?riotx_text_secondary"
android:textSize="15sp"
app:layout_constraintBottom_toBottomOf="@id/knownMember1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/knownMember5"
app:layout_constraintTop_toTopOf="@id/knownMember1"
tools:text="7 people you may know" />
<ImageView
android:id="@+id/knownMember4"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@string/avatar"
app:layout_constraintCircle="@id/knownMember3"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="20dp"
tools:ignore="MissingConstraints"
tools:src="@tools:sample/avatars"
tools:visibility="gone" />
<com.google.android.material.button.MaterialButton
android:id="@+id/matrixToCardMainButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="@dimen/layout_vertical_margin_big"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/knownMember1"
app:layout_constraintWidth_max="400dp"
tools:text="@string/join" />
<ImageView
android:id="@+id/knownMember3"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@string/avatar"
app:layout_constraintCircle="@id/knownMember2"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="20dp"
tools:ignore="MissingConstraints"
tools:src="@tools:sample/avatars" />
<com.google.android.material.button.MaterialButton
android:id="@+id/matrixToCardSecondaryButton"
style="@style/VectorButtonStyleOutlined"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="@dimen/layout_vertical_margin_big"
android:textAllCaps="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/matrixToCardMainButton"
app:layout_constraintWidth_max="400dp"
tools:text="@string/dismiss" />
<ImageView
android:id="@+id/knownMember2"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@string/avatar"
app:layout_constraintCircle="@id/knownMember1"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="20dp"
tools:ignore="MissingConstraints"
tools:src="@tools:sample/avatars" />
<ImageView
android:id="@+id/knownMember1"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="8dp"
android:contentDescription="@string/avatar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/matrixToCardDescText"
tools:src="@tools:sample/avatars" />
<TextView
android:id="@+id/peopleYouMayKnowText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:textColor="?riotx_text_secondary"
android:textSize="15sp"
app:layout_constraintBottom_toBottomOf="@id/knownMember1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/knownMember5"
app:layout_constraintTop_toTopOf="@id/knownMember1"
tools:text="7 people you may know" />
<im.vector.app.core.platform.ButtonStateView
android:id="@+id/matrixToCardMainButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="@dimen/layout_vertical_margin_big"
app:bsv_button_text="@string/accept"
app:bsv_loaded_image_src="@drawable/ic_tick"
app:bsv_use_flat_button="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/knownMember1"
app:layout_constraintWidth_max="400dp" />
<!-- <com.google.android.material.button.MaterialButton-->
<!-- android:id="@+id/matrixToCardMainButton"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginTop="16dp"-->
<!-- android:layout_marginBottom="@dimen/layout_vertical_margin_big"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/knownMember1"-->
<!-- app:layout_constraintWidth_max="400dp"-->
<!-- tools:text="@string/join" />-->
<!-- <com.google.android.material.button.MaterialButton-->
<!-- android:id="@+id/matrixToCardSecondaryButton"-->
<!-- style="@style/VectorButtonStyleOutlined"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginTop="8dp"-->
<!-- android:layout_marginBottom="@dimen/layout_vertical_margin_big"-->
<!-- android:textAllCaps="true"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/matrixToCardMainButton"-->
<!-- app:layout_constraintWidth_max="400dp"-->
<!-- tools:text="@string/dismiss" />-->
<im.vector.app.core.platform.ButtonStateView
android:id="@+id/matrixToCardSecondaryButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="@dimen/layout_vertical_margin_big"
app:bsv_button_text="@string/dismiss"
app:bsv_loaded_image_src="@drawable/ic_tick"
app:bsv_use_flat_button="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/matrixToCardMainButton"
app:layout_constraintWidth_max="400dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ProgressBar
android:id="@+id/matrixToCardButtonLoading"
style="?android:attr/progressBarStyleSmall"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_centerInParent="true"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/matrixToCardMainButton"
app:layout_constraintEnd_toEndOf="@id/matrixToCardMainButton"
app:layout_constraintStart_toStartOf="@id/matrixToCardMainButton"
app:layout_constraintTop_toTopOf="@id/matrixToCardMainButton"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Group
android:id="@+id/matrixToCardPeopleYouKnowVisibility"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="knownMember1,knownMember2,knownMember3,knownMember4,knownMember5,peopleYouMayKnowText"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Group
android:id="@+id/matrixToCardContentVisibility"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="matrixToCardNameText,matrixToCardAvatar,matrixToCardNameText,matrixToCardDescText, matrixToCardMainButton, matrixToCardAliasText, matrixToCardSecondaryButton, matrixToMemberPills,matrixToCardPeopleYouKnowVisibility"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:parentTag="android.widget.FrameLayout">
<com.google.android.material.button.MaterialButton
android:id="@+id/buttonStateButtonFlat"
style="@style/VectorButtonStyleText"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
tools:layout_gravity="center_horizontal"
@ -16,7 +16,7 @@
<com.google.android.material.button.MaterialButton
android:id="@+id/buttonStateButtonBig"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:minWidth="120dp"

View file

@ -3341,4 +3341,5 @@
<string name="labs_use_restricted_join_rule">Experimental Space - Restricted Room.</string>
<string name="labs_use_restricted_join_rule_desc">Warning requires server support and experimental room version</string>
<string name="user_invites_you">%s invites you</string>
</resources>

View file

@ -152,7 +152,7 @@
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">@null</item>
<!--item name="android:textColor">?colorAccent</item-->
<item name="android:textColor">?colorAccent</item>
<item name="colorControlHighlight">?colorAccent</item>
</style>
@ -162,7 +162,7 @@
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">@null</item>
<!--item name="android:textColor">?colorAccent</item-->
<item name="android:textColor">?colorAccent</item>
<item name="colorControlHighlight">?colorAccent</item>
<item name="strokeColor">@color/button_background_tint_selector</item>
<item name="strokeWidth">1dp</item>