diff --git a/app/src/main/java/org/futo/circles/feature/room/ManageMembersOptionsListener.kt b/app/src/main/java/org/futo/circles/feature/room/ManageMembersOptionsListener.kt index 209fe7d5621d3e40a5ce59abccde1f886356a41c..8a284bc7b262ec343de8f3c943ce8cd76d8dd497 100644 --- a/app/src/main/java/org/futo/circles/feature/room/ManageMembersOptionsListener.kt +++ b/app/src/main/java/org/futo/circles/feature/room/ManageMembersOptionsListener.kt @@ -8,4 +8,5 @@ interface ManageMembersOptionsListener { fun onBanUser(userId: String) fun unBanUser(userId: String) fun cancelPendingInvitation(userId: String) + fun resendInvitation(userId: String) } \ No newline at end of file diff --git a/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersDataSource.kt b/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersDataSource.kt index 3c690996593eccea9649c614555e7ed8ca71d694..38c5c94a27f1540707e9bf758d55786618860c2f 100644 --- a/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersDataSource.kt +++ b/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersDataSource.kt @@ -4,7 +4,6 @@ package org.futo.circles.feature.room.manage_members import android.content.Context import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.asFlow -import dagger.assisted.AssistedFactory import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.scopes.ViewModelScoped import kotlinx.coroutines.Dispatchers @@ -22,12 +21,14 @@ import org.futo.circles.core.extensions.getOrThrow import org.futo.circles.core.mapping.nameOrId import org.futo.circles.core.model.CircleRoomTypeArg import org.futo.circles.core.provider.MatrixSessionProvider +import org.futo.circles.mapping.toBannedUserListItem import org.futo.circles.mapping.toGroupMemberListItem -import org.futo.circles.mapping.toNotJoinedUserListItem +import org.futo.circles.mapping.toInvitedMemberListItem +import org.futo.circles.model.BannedMemberListItem import org.futo.circles.model.GroupMemberListItem +import org.futo.circles.model.InvitedMemberListItem import org.futo.circles.model.ManageMembersHeaderListItem import org.futo.circles.model.ManageMembersListItem -import org.futo.circles.model.NotJoinedUserListItem import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent @@ -90,17 +91,20 @@ class ManageMembersDataSource @Inject constructor( val roleHelper = PowerLevelsHelper(powerLevelsContent) val fullList = mutableListOf<ManageMembersListItem>() val currentMembers = mutableListOf<GroupMemberListItem>() - val invitedUsers = mutableListOf<NotJoinedUserListItem>() - val bannedUsers = mutableListOf<NotJoinedUserListItem>() + val invitedUsers = mutableListOf<InvitedMemberListItem>() + val bannedUsers = mutableListOf<BannedMemberListItem>() members.forEach { member -> when (member.membership) { Membership.INVITE -> invitedUsers.add( - member.toNotJoinedUserListItem(powerLevelsContent) + member.toInvitedMemberListItem( + usersWithVisibleOptions.contains(member.userId), + powerLevelsContent + ) ) Membership.BAN -> bannedUsers.add( - member.toNotJoinedUserListItem(powerLevelsContent) + member.toBannedUserListItem(powerLevelsContent) ) Membership.JOIN -> currentMembers.add( @@ -132,6 +136,12 @@ class ManageMembersDataSource @Inject constructor( suspend fun removeUser(userId: String) = createResult { room?.membershipService()?.remove(userId) } + suspend fun reInviteUser(userId: String) = + createResult { + room?.membershipService()?.remove(userId) + room?.membershipService()?.invite(userId) + } + suspend fun banUser(userId: String) = createResult { room?.membershipService()?.ban(userId) } suspend fun unBanUser(userId: String) = @@ -141,5 +151,6 @@ class ManageMembersDataSource @Inject constructor( val content = powerLevelsContent?.setUserPowerLevel(userId, levelValue).toContent() room?.stateService() ?.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", content) + Unit } } \ No newline at end of file diff --git a/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersDialogFragment.kt b/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersDialogFragment.kt index b7e406dc1f4c4deb884271fc298f8a4529859ae8..972ad8d60e462902089070fe97d5616ac7b8cac2 100644 --- a/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersDialogFragment.kt +++ b/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersDialogFragment.kt @@ -21,6 +21,7 @@ import org.futo.circles.feature.room.manage_members.list.GroupMembersListAdapter import org.futo.circles.model.BanUser import org.futo.circles.model.CancelInvite import org.futo.circles.model.RemoveRoomUser +import org.futo.circles.model.ResendInvite import org.futo.circles.model.UnbanUser import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent @@ -63,9 +64,7 @@ class ManageMembersDialogFragment : viewModel.groupMembersLiveData.observeData(this) { membersListAdapter.submitList(it) } - viewModel.removeUserResultLiveData.observeResponse(this) - viewModel.banUserResultLiveData.observeResponse(this) - viewModel.changeAccessLevelLiveData.observeResponse(this) + viewModel.responseLiveData.observeResponse(this) } @@ -100,4 +99,8 @@ class ManageMembersDialogFragment : withConfirmation(CancelInvite()) { viewModel.removeUser(userId) } } + override fun resendInvitation(userId: String) { + withConfirmation(ResendInvite()) { viewModel.resendInvitation(userId) } + } + } \ No newline at end of file diff --git a/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersViewModel.kt b/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersViewModel.kt index c4df221b26e3051c623e0054aa0d3afa8ea684be..4c1b2e36484b68f8db69a28ba2af9616a51945ed 100644 --- a/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersViewModel.kt +++ b/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersViewModel.kt @@ -17,9 +17,7 @@ class ManageMembersViewModel @Inject constructor( val titleLiveData = MutableLiveData(dataSource.getManageMembersTittle()) val groupMembersLiveData = dataSource.getRoomMembersFlow().asLiveData() - val removeUserResultLiveData = SingleEventLiveData<Response<Unit?>>() - val banUserResultLiveData = SingleEventLiveData<Response<Unit?>>() - val changeAccessLevelLiveData = SingleEventLiveData<Response<String?>>() + val responseLiveData = SingleEventLiveData<Response<Unit?>>() fun toggleOptionsVisibility(userId: String) { dataSource.toggleOptionsVisibilityFor(userId) @@ -27,20 +25,26 @@ class ManageMembersViewModel @Inject constructor( fun removeUser(userId: String) { - launchBg { removeUserResultLiveData.postValue(dataSource.removeUser(userId)) } + launchBg { responseLiveData.postValue(dataSource.removeUser(userId)) } } fun banUser(userId: String) { - launchBg { banUserResultLiveData.postValue(dataSource.banUser(userId)) } + launchBg { responseLiveData.postValue(dataSource.banUser(userId)) } } fun unBanUser(userId: String) { - launchBg { banUserResultLiveData.postValue(dataSource.unBanUser(userId)) } + launchBg { responseLiveData.postValue(dataSource.unBanUser(userId)) } } fun changeAccessLevel(userId: String, levelValue: Int) { launchBg { - changeAccessLevelLiveData.postValue(dataSource.changeAccessLevel(userId, levelValue)) + responseLiveData.postValue(dataSource.changeAccessLevel(userId, levelValue)) + } + } + + fun resendInvitation(userId: String) { + launchBg { + responseLiveData.postValue(dataSource.reInviteUser(userId)) } } } \ No newline at end of file diff --git a/app/src/main/java/org/futo/circles/feature/room/manage_members/list/MemberViewHolder.kt b/app/src/main/java/org/futo/circles/feature/room/manage_members/list/MemberViewHolder.kt index e838f2b5e2ae657b1fa77fb683ebba09de915ed4..12fe67738a53fd79b67faca7447ae8d26b363533 100644 --- a/app/src/main/java/org/futo/circles/feature/room/manage_members/list/MemberViewHolder.kt +++ b/app/src/main/java/org/futo/circles/feature/room/manage_members/list/MemberViewHolder.kt @@ -8,20 +8,20 @@ import org.futo.circles.core.databinding.ListItemInviteHeaderBinding import org.futo.circles.core.extensions.getRoleNameResId import org.futo.circles.core.extensions.gone import org.futo.circles.core.extensions.isCurrentUserAbleToBan -import org.futo.circles.core.extensions.isCurrentUserAbleToKick import org.futo.circles.core.extensions.onClick import org.futo.circles.core.extensions.setIsVisible import org.futo.circles.core.extensions.visible import org.futo.circles.core.list.ViewBindingHolder import org.futo.circles.core.list.context +import org.futo.circles.databinding.ListItemBannedMemberBinding +import org.futo.circles.databinding.ListItemInvitedMemberBinding import org.futo.circles.databinding.ListItemMemberBinding -import org.futo.circles.databinding.ListItemNotJoinedUserBinding import org.futo.circles.feature.room.ManageMembersOptionsListener +import org.futo.circles.model.BannedMemberListItem import org.futo.circles.model.GroupMemberListItem +import org.futo.circles.model.InvitedMemberListItem import org.futo.circles.model.ManageMembersHeaderListItem import org.futo.circles.model.ManageMembersListItem -import org.futo.circles.model.NotJoinedUserListItem -import org.matrix.android.sdk.api.session.room.model.Membership abstract class ManageMembersViewHolder(view: View) : RecyclerView.ViewHolder(view) { abstract fun bind(data: ManageMembersListItem) @@ -77,40 +77,62 @@ class ManageMembersHeaderViewHolder( } } -class NotJoinedUserViewHolder( +class InvitedMemberViewHolder( parent: ViewGroup, - private val manageMembersListener: ManageMembersOptionsListener, -) : ManageMembersViewHolder(inflate(parent, ListItemNotJoinedUserBinding::inflate)) { + private val onUserClicked: (Int) -> Unit, + private val manageMembersListener: ManageMembersOptionsListener +) : ManageMembersViewHolder(inflate(parent, ListItemInvitedMemberBinding::inflate)) { private companion object : ViewBindingHolder - private val binding = baseBinding as ListItemNotJoinedUserBinding + private val binding = baseBinding as ListItemInvitedMemberBinding override fun bind(data: ManageMembersListItem) { - if (data !is NotJoinedUserListItem) return - - binding.lUser.bind(data.user) + if (data !is InvitedMemberListItem) return - when (data.membership) { - Membership.INVITE -> { - binding.tvStatus.text = context.getString(R.string.invited) - val isAbleToKick = data.powerLevelsContent.isCurrentUserAbleToKick() - binding.ivRemove.setIsVisible(isAbleToKick) - if (isAbleToKick) binding.ivRemove.setOnClickListener { + with(binding) { + vUser.bind(data.user) + if (data.isOptionsAvailable) { + ivOptionsArrow.visible() + ivOptionsArrow.setImageResource( + if (data.isOptionsOpened) R.drawable.ic_keyboard_arrow_up + else R.drawable.ic_keyboard_arrow_down + ) + onClick(binding.contentLayout) { position -> onUserClicked(position) } + binding.optionsLayout.setIsVisible(data.isOptionsOpened) + binding.btnRemove.setOnClickListener { manageMembersListener.cancelPendingInvitation(data.user.id) } - } - - Membership.BAN -> { - binding.tvStatus.text = context.getString(R.string.banned) - val isAbleToBan = data.powerLevelsContent.isCurrentUserAbleToBan() - binding.ivRemove.setIsVisible(isAbleToBan) - if (isAbleToBan) binding.ivRemove.setOnClickListener { - manageMembersListener.unBanUser(data.user.id) + binding.btnResend.setOnClickListener { + manageMembersListener.resendInvitation(data.user.id) } + } else { + ivOptionsArrow.gone() + binding.contentLayout.setOnClickListener(null) } + } + } +} + + +class BannedMemberViewHolder( + parent: ViewGroup, + private val manageMembersListener: ManageMembersOptionsListener, +) : ManageMembersViewHolder(inflate(parent, ListItemBannedMemberBinding::inflate)) { + + private companion object : ViewBindingHolder + + private val binding = baseBinding as ListItemBannedMemberBinding + + override fun bind(data: ManageMembersListItem) { + if (data !is BannedMemberListItem) return + + binding.lUser.bind(data.user) - else -> return + val isAbleToBan = data.powerLevelsContent.isCurrentUserAbleToBan() + binding.ivRemove.setIsVisible(isAbleToBan) + if (isAbleToBan) binding.ivRemove.setOnClickListener { + manageMembersListener.unBanUser(data.user.id) } } } \ No newline at end of file diff --git a/app/src/main/java/org/futo/circles/feature/room/manage_members/list/MembersListAdapter.kt b/app/src/main/java/org/futo/circles/feature/room/manage_members/list/MembersListAdapter.kt index 2dc38ce37116fe916b55d1e2c38e43dcda6cfd0f..0898d2430949621b0cd1111e6b8603afe6775969 100644 --- a/app/src/main/java/org/futo/circles/feature/room/manage_members/list/MembersListAdapter.kt +++ b/app/src/main/java/org/futo/circles/feature/room/manage_members/list/MembersListAdapter.kt @@ -3,12 +3,13 @@ package org.futo.circles.feature.room.manage_members.list import android.view.ViewGroup import org.futo.circles.core.list.BaseRvAdapter import org.futo.circles.feature.room.ManageMembersOptionsListener +import org.futo.circles.model.BannedMemberListItem import org.futo.circles.model.GroupMemberListItem +import org.futo.circles.model.InvitedMemberListItem import org.futo.circles.model.ManageMembersHeaderListItem import org.futo.circles.model.ManageMembersListItem -import org.futo.circles.model.NotJoinedUserListItem -private enum class ManageGroupMembersViewTypes { Header, Member, NotJoined } +private enum class ManageGroupMembersViewTypes { Header, Member, Invited, Banned } class GroupMembersListAdapter( private val manageMembersListener: ManageMembersOptionsListener, @@ -20,7 +21,8 @@ class GroupMembersListAdapter( override fun getItemViewType(position: Int): Int = when (getItem(position)) { is ManageMembersHeaderListItem -> ManageGroupMembersViewTypes.Header.ordinal is GroupMemberListItem -> ManageGroupMembersViewTypes.Member.ordinal - is NotJoinedUserListItem -> ManageGroupMembersViewTypes.NotJoined.ordinal + is InvitedMemberListItem -> ManageGroupMembersViewTypes.Invited.ordinal + is BannedMemberListItem -> ManageGroupMembersViewTypes.Banned.ordinal } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ManageMembersViewHolder { @@ -31,7 +33,14 @@ class GroupMembersListAdapter( onUserClicked = { position -> onToggleOptions(getItem(position).id) }, manageMembersListener = manageMembersListener ) - ManageGroupMembersViewTypes.NotJoined -> NotJoinedUserViewHolder( + + ManageGroupMembersViewTypes.Invited -> InvitedMemberViewHolder( + parent = parent, + onUserClicked = { position -> onToggleOptions(getItem(position).id) }, + manageMembersListener = manageMembersListener + ) + + ManageGroupMembersViewTypes.Banned -> BannedMemberViewHolder( parent, manageMembersListener, ) } diff --git a/app/src/main/java/org/futo/circles/mapping/RoomMemberSummaryMapping.kt b/app/src/main/java/org/futo/circles/mapping/RoomMemberSummaryMapping.kt index 7c342fe48f99e9af1bff180fd55bdf932ced6ddd..f54f0307d0bc54b63a76f4f3307634b0fa8821a8 100644 --- a/app/src/main/java/org/futo/circles/mapping/RoomMemberSummaryMapping.kt +++ b/app/src/main/java/org/futo/circles/mapping/RoomMemberSummaryMapping.kt @@ -1,8 +1,9 @@ package org.futo.circles.mapping import org.futo.circles.core.model.CirclesUserSummary +import org.futo.circles.model.BannedMemberListItem import org.futo.circles.model.GroupMemberListItem -import org.futo.circles.model.NotJoinedUserListItem +import org.futo.circles.model.InvitedMemberListItem import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.powerlevels.Role @@ -24,9 +25,14 @@ fun RoomMemberSummary.toGroupMemberListItem( powerLevelsContent = powerLevelsContent ) -fun RoomMemberSummary.toNotJoinedUserListItem(powerLevelsContent: PowerLevelsContent) = - NotJoinedUserListItem( - user = toCircleUserSummary(), - powerLevelsContent = powerLevelsContent, - membership = membership - ) \ No newline at end of file +fun RoomMemberSummary.toInvitedMemberListItem( + isOptionsVisible: Boolean, + powerLevelsContent: PowerLevelsContent +) = InvitedMemberListItem( + user = toCircleUserSummary(), + isOptionsOpened = isOptionsVisible, + powerLevelsContent = powerLevelsContent +) + +fun RoomMemberSummary.toBannedUserListItem(powerLevelsContent: PowerLevelsContent) = + BannedMemberListItem(user = toCircleUserSummary(), powerLevelsContent = powerLevelsContent) \ No newline at end of file diff --git a/app/src/main/java/org/futo/circles/model/ConfirmationType.kt b/app/src/main/java/org/futo/circles/model/ConfirmationType.kt index 6e8ff2f3920878f2ca25666d3812e9e2f80d37e2..4b294ba0da61df24d2832167dc5af6519c623eb1 100644 --- a/app/src/main/java/org/futo/circles/model/ConfirmationType.kt +++ b/app/src/main/java/org/futo/circles/model/ConfirmationType.kt @@ -89,6 +89,12 @@ data class CancelInvite( override val positiveButtonRes: Int = android.R.string.ok ) : ConfirmationType(titleRes, messageRes, positiveButtonRes) +data class ResendInvite( + override val titleRes: Int = R.string.resend_invite, + override val messageRes: Int = R.string.resend_invite_message, + override val positiveButtonRes: Int = android.R.string.ok +) : ConfirmationType(titleRes, messageRes, positiveButtonRes) + data class RemoveSession( override val titleRes: Int = R.string.remove_session, override val messageRes: Int = R.string.remove_session_message, diff --git a/app/src/main/java/org/futo/circles/model/GroupMemberListItem.kt b/app/src/main/java/org/futo/circles/model/GroupMemberListItem.kt index a004e475810377f6e37b2bf3093824e4c55ad2d6..6625dae241133828dfe123231e68155b0a93f3a1 100644 --- a/app/src/main/java/org/futo/circles/model/GroupMemberListItem.kt +++ b/app/src/main/java/org/futo/circles/model/GroupMemberListItem.kt @@ -3,6 +3,7 @@ package org.futo.circles.model import org.futo.circles.core.extensions.getCurrentUserPowerLevel import org.futo.circles.core.extensions.isCurrentUserAbleToBan import org.futo.circles.core.extensions.isCurrentUserAbleToChangeSettings +import org.futo.circles.core.extensions.isCurrentUserAbleToInvite import org.futo.circles.core.extensions.isCurrentUserAbleToKick import org.futo.circles.core.list.IdEntity import org.futo.circles.core.model.CirclesUserSummary @@ -37,10 +38,22 @@ data class GroupMemberListItem( } -data class NotJoinedUserListItem( +data class InvitedMemberListItem( val user: CirclesUserSummary, val powerLevelsContent: PowerLevelsContent, - val membership: Membership + val membership: Membership = Membership.INVITE, + val isOptionsOpened: Boolean +) : ManageMembersListItem() { + override val id: String = user.id + + val isOptionsAvailable = (powerLevelsContent.isCurrentUserAbleToInvite() || + powerLevelsContent.isCurrentUserAbleToKick()) +} + +data class BannedMemberListItem( + val user: CirclesUserSummary, + val powerLevelsContent: PowerLevelsContent, + val membership: Membership = Membership.BAN ) : ManageMembersListItem() { override val id: String = user.id } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_resend.xml b/app/src/main/res/drawable/ic_resend.xml new file mode 100644 index 0000000000000000000000000000000000000000..96e77eca3d9d448c0d1bb30bfff811566b5b2c4c --- /dev/null +++ b/app/src/main/res/drawable/ic_resend.xml @@ -0,0 +1,5 @@ +<vector android:height="24dp" android:tint="#FFFFFF" + android:viewportHeight="24" android:viewportWidth="24" + android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="@android:color/white" android:pathData="M12,5V1L7,6l5,5V7c3.31,0 6,2.69 6,6s-2.69,6 -6,6 -6,-2.69 -6,-6H4c0,4.42 3.58,8 8,8s8,-3.58 8,-8 -3.58,-8 -8,-8z"/> +</vector> diff --git a/app/src/main/res/layout/list_item_not_joined_user.xml b/app/src/main/res/layout/list_item_banned_member.xml similarity index 92% rename from app/src/main/res/layout/list_item_not_joined_user.xml rename to app/src/main/res/layout/list_item_banned_member.xml index 3fdad0e74a10ac9d3d36d34cfbad80ccad317e3f..92fcaa47bfc8513da12ab3d4c8e10a5474e7874a 100644 --- a/app/src/main/res/layout/list_item_not_joined_user.xml +++ b/app/src/main/res/layout/list_item_banned_member.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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:paddingVertical="4dp"> @@ -21,11 +20,11 @@ android:layout_marginEnd="16dp" android:ellipsize="end" android:lines="1" + android:text="@string/banned" android:textSize="13sp" app:layout_constraintBottom_toBottomOf="@id/lUser" app:layout_constraintEnd_toStartOf="@id/ivRemove" - app:layout_constraintTop_toTopOf="@id/lUser" - tools:text="@string/invited" /> + app:layout_constraintTop_toTopOf="@id/lUser" /> <ImageView android:id="@+id/ivRemove" diff --git a/app/src/main/res/layout/list_item_invited_member.xml b/app/src/main/res/layout/list_item_invited_member.xml new file mode 100644 index 0000000000000000000000000000000000000000..3ac254e6dfa083e3dd43a871aa65df7926e2e260 --- /dev/null +++ b/app/src/main/res/layout/list_item_invited_member.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout 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"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:id="@+id/contentLayout" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:background="?selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:paddingVertical="4dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> + + + <org.futo.circles.core.view.UserListItemView + android:id="@+id/vUser" + android:layout_width="0dp" + android:layout_height="wrap_content" + app:layout_constraintEnd_toStartOf="@id/tvStatus" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <TextView + android:id="@+id/tvStatus" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="16dp" + android:ellipsize="end" + android:lines="1" + android:text="@string/invited" + android:textSize="13sp" + app:layout_constraintBottom_toBottomOf="@id/vUser" + app:layout_constraintEnd_toStartOf="@id/ivOptionsArrow" + app:layout_constraintTop_toTopOf="@id/vUser" /> + + <ImageView + android:id="@+id/ivOptionsArrow" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:src="@drawable/ic_keyboard_arrow_down" + app:layout_constraintBottom_toBottomOf="@id/vUser" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:tint="@color/blue" /> + + </androidx.constraintlayout.widget.ConstraintLayout> + + + <androidx.constraintlayout.widget.ConstraintLayout + android:id="@+id/optionsLayout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/contentLayout" + tools:visibility="visible"> + + <View + android:id="@+id/divider" + android:layout_width="0dp" + android:layout_height="@dimen/divider_height" + android:background="@color/divider_color" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <com.google.android.material.button.MaterialButton + android:id="@+id/btnResend" + style="@style/PostButtonStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/resend" + app:icon="@drawable/ic_resend" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@id/btnRemove" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/divider" /> + + <com.google.android.material.button.MaterialButton + android:id="@+id/btnRemove" + style="@style/PostButtonStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/remove" + app:icon="@drawable/ic_person_remove" + app:iconPadding="10dp" + app:layout_constraintBottom_toBottomOf="@id/btnResend" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/btnResend" + app:layout_constraintTop_toTopOf="@id/btnResend" /> + + + </androidx.constraintlayout.widget.ConstraintLayout> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 46cb0d6d0dcb4423995759e296312bba1cc088b9..3e906f35166f72e5f4bf33f9765d9edc01d5d4ba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -66,7 +66,9 @@ <string name="banned">Banned</string> <string name="invited">Invited</string> <string name="cancel_invite">Cancel invite</string> + <string name="resend_invite">Resend invite</string> <string name="cancel_invite_message">Are you sure you want to cancel the invite for this user?</string> + <string name="resend_invite_message">Are you sure you want to cancel and resend the invite for this user?</string> <string name="remove_user_in_room_message">Are you sure you want to remove this user?\n\nUser still be able to join by invite.</string> <string name="ban_user">Ban user</string> <string name="ban_user_message">Are you sure you want to ban this user?\n\nUser will not be able to join again.</string> @@ -309,6 +311,7 @@ <string name="you_are_already_following_user">You are already following this user</string> <string name="you_are_banned_user">You are banned</string> <string name="send_request_to_follow_user">Send request to follow this user</string> + <string name="resend">Resend</string> <string-array name="report_categories"> <item>@string/crude_language</item>