From a3b33c7e89bc3859d4ea5489f5a6d7a6b16f9ef8 Mon Sep 17 00:00:00 2001 From: Taras Smakula <tarassmakula@gmail.com> Date: Tue, 26 Dec 2023 16:19:04 +0200 Subject: [PATCH] Create new base view holder for invites --- .../feature/groups/list/GroupViewHolder.kt | 2 +- .../org/futo/circles/view/PostHeaderView.kt | 2 +- .../room/invites/list/InvitesViewHolder.kt | 161 ++++++++++++++++++ .../res/layout/list_item_invited_circle.xml | 0 .../res/layout/list_item_invited_group.xml | 0 .../res/layout/list_item_people_request.xml | 96 +++++++++++ 6 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/futo/circles/core/feature/room/invites/list/InvitesViewHolder.kt rename {app => core}/src/main/res/layout/list_item_invited_circle.xml (100%) rename {app => core}/src/main/res/layout/list_item_invited_group.xml (100%) create mode 100644 core/src/main/res/layout/list_item_people_request.xml diff --git a/app/src/main/java/org/futo/circles/feature/groups/list/GroupViewHolder.kt b/app/src/main/java/org/futo/circles/feature/groups/list/GroupViewHolder.kt index 19ce4ece1..5d1a0e4b6 100644 --- a/app/src/main/java/org/futo/circles/feature/groups/list/GroupViewHolder.kt +++ b/app/src/main/java/org/futo/circles/feature/groups/list/GroupViewHolder.kt @@ -12,9 +12,9 @@ import org.futo.circles.core.base.list.context import org.futo.circles.core.databinding.ListItemInviteNotificationBinding import org.futo.circles.core.extensions.loadRoomProfileIcon import org.futo.circles.core.extensions.onClick +import org.futo.circles.core.extensions.setIsEncryptedIcon import org.futo.circles.core.extensions.setIsVisible import org.futo.circles.databinding.ListItemJoinedGroupBinding -import org.futo.circles.extensions.setIsEncryptedIcon import org.futo.circles.model.GroupInvitesNotificationListItem import org.futo.circles.model.GroupListItem import org.futo.circles.model.GroupListItemPayload diff --git a/app/src/main/java/org/futo/circles/view/PostHeaderView.kt b/app/src/main/java/org/futo/circles/view/PostHeaderView.kt index c6d3f16bc..90d4d4dc2 100644 --- a/app/src/main/java/org/futo/circles/view/PostHeaderView.kt +++ b/app/src/main/java/org/futo/circles/view/PostHeaderView.kt @@ -9,12 +9,12 @@ import org.futo.circles.R import org.futo.circles.core.extensions.getAttributes import org.futo.circles.core.extensions.loadUserProfileIcon import org.futo.circles.core.extensions.notEmptyDisplayName +import org.futo.circles.core.extensions.setIsEncryptedIcon import org.futo.circles.core.extensions.setIsVisible import org.futo.circles.core.model.Post import org.futo.circles.core.provider.MatrixSessionProvider import org.futo.circles.core.utils.UserUtils import org.futo.circles.databinding.ViewPostHeaderBinding -import org.futo.circles.extensions.setIsEncryptedIcon import java.util.Date class PostHeaderView( diff --git a/core/src/main/java/org/futo/circles/core/feature/room/invites/list/InvitesViewHolder.kt b/core/src/main/java/org/futo/circles/core/feature/room/invites/list/InvitesViewHolder.kt new file mode 100644 index 000000000..a82827046 --- /dev/null +++ b/core/src/main/java/org/futo/circles/core/feature/room/invites/list/InvitesViewHolder.kt @@ -0,0 +1,161 @@ +package org.futo.circles.core.feature.room.invites.list + +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import org.futo.circles.core.R +import org.futo.circles.core.base.list.ViewBindingHolder +import org.futo.circles.core.base.list.context +import org.futo.circles.core.databinding.ListItemInvitedCircleBinding +import org.futo.circles.core.databinding.ListItemInvitedGalleryBinding +import org.futo.circles.core.databinding.ListItemInvitedGroupBinding +import org.futo.circles.core.databinding.ListItemPeopleRequestBinding +import org.futo.circles.core.extensions.loadRoomProfileIcon +import org.futo.circles.core.extensions.loadUserProfileIcon +import org.futo.circles.core.extensions.onClick +import org.futo.circles.core.extensions.setIsEncryptedIcon +import org.futo.circles.core.extensions.setIsVisible +import org.futo.circles.core.model.CirclesUserSummary +import org.futo.circles.core.model.FollowRequestListItem +import org.futo.circles.core.model.InviteListItem +import org.futo.circles.core.model.RoomInviteListItem + +abstract class InviteViewHolder(view: View) : RecyclerView.ViewHolder(view) { + abstract fun bind(data: InviteListItem) +} + + +class InvitedGroupViewHolder( + parent: ViewGroup, + onInviteClicked: (Int, Boolean) -> Unit, + onShowProfileIconClicked: (Int) -> Unit +) : InviteViewHolder(inflate(parent, ListItemInvitedGroupBinding::inflate)) { + + private companion object : ViewBindingHolder + + private val binding = baseBinding as ListItemInvitedGroupBinding + + init { + onClick(binding.btnAccept) { position -> onInviteClicked(position, true) } + onClick(binding.btnDecline) { position -> onInviteClicked(position, false) } + onClick(binding.ivGroup) { position -> onShowProfileIconClicked(position) } + } + + override fun bind(data: InviteListItem) { + if (data !is RoomInviteListItem) return + + with(binding) { + ivGroup.loadRoomProfileIcon( + data.info.avatarUrl, + data.info.title, + applyBlur = data.shouldBlurIcon + ) + tvShowProfileImage.setIsVisible(data.shouldBlurIcon) + ivLock.setIsEncryptedIcon(data.isEncrypted) + tvGroupTitle.text = data.info.title + tvInviterName.text = context.getString( + R.string.invited_by_format, + data.inviterName + ) + } + } +} + +class InvitedCircleViewHolder( + parent: ViewGroup, + onInviteClicked: (Int, Boolean) -> Unit, + onShowProfileIconClicked: (Int) -> Unit +) : InviteViewHolder(inflate(parent, ListItemInvitedCircleBinding::inflate)) { + + private companion object : ViewBindingHolder + + private val binding = baseBinding as ListItemInvitedCircleBinding + + init { + onClick(binding.btnAccept) { position -> onInviteClicked(position, true) } + onClick(binding.btnDecline) { position -> onInviteClicked(position, false) } + onClick(binding.ivCircle) { position -> onShowProfileIconClicked(position) } + } + + override fun bind(data: InviteListItem) { + if (data !is RoomInviteListItem) return + + with(binding) { + tvShowProfileImage.setIsVisible(data.shouldBlurIcon) + ivCircle.loadRoomProfileIcon( + data.info.avatarUrl, + data.info.title, + applyBlur = data.shouldBlurIcon + ) + tvCircleTitle.text = data.info.title + binding.tvInvitedBy.text = + context.getString( + R.string.invited_by_format, + data.inviterName + ) + } + } +} + +class InvitedGalleryViewHolder( + parent: ViewGroup, + onInviteClicked: (Int, Boolean) -> Unit, + onShowProfileIconClicked: (Int) -> Unit +) : InviteViewHolder(inflate(parent, ListItemInvitedGalleryBinding::inflate)) { + + private companion object : ViewBindingHolder + + private val binding = baseBinding as ListItemInvitedGalleryBinding + + init { + onClick(binding.btnAccept) { position -> onInviteClicked(position, true) } + onClick(binding.btnDecline) { position -> onInviteClicked(position, false) } + onClick(binding.ivGallery) { position -> onShowProfileIconClicked(position) } + } + + override fun bind(data: InviteListItem) { + if (data !is RoomInviteListItem) return + + with(binding) { + tvGalleryTitle.text = data.info.title + ivGallery.loadRoomProfileIcon( + data.info.avatarUrl, + data.info.title, + applyBlur = data.shouldBlurIcon + ) + tvShowProfileImage.setIsVisible(data.shouldBlurIcon) + tvInviterName.text = context.getString(R.string.invited_by_format, data.inviterName) + } + } +} + +class FollowRequestViewHolder( + parent: ViewGroup, + private val onRequestClicked: (Int, Boolean) -> Unit +) : InviteViewHolder(inflate(parent, ListItemPeopleRequestBinding::inflate)) { + + private companion object : ViewBindingHolder + + private val binding = baseBinding as ListItemPeopleRequestBinding + + init { + onClick(binding.btnAccept) { position -> onRequestClicked(position, true) } + onClick(binding.btnDecline) { position -> onRequestClicked(position, false) } + } + + override fun bind(data: InviteListItem) { + val user = (data as? FollowRequestListItem)?.user ?: return + bindUser(user) + binding.tvReasonMessage.apply { + setIsVisible(data.reasonMessage != null) + text = data.reasonMessage + } + } + + private fun bindUser(user: CirclesUserSummary) { + with(binding) { + tvUserName.text = user.name + ivUserImage.loadUserProfileIcon(user.avatarUrl, user.id) + } + } +} diff --git a/app/src/main/res/layout/list_item_invited_circle.xml b/core/src/main/res/layout/list_item_invited_circle.xml similarity index 100% rename from app/src/main/res/layout/list_item_invited_circle.xml rename to core/src/main/res/layout/list_item_invited_circle.xml diff --git a/app/src/main/res/layout/list_item_invited_group.xml b/core/src/main/res/layout/list_item_invited_group.xml similarity index 100% rename from app/src/main/res/layout/list_item_invited_group.xml rename to core/src/main/res/layout/list_item_invited_group.xml diff --git a/core/src/main/res/layout/list_item_people_request.xml b/core/src/main/res/layout/list_item_people_request.xml new file mode 100644 index 000000000..1c760fdfa --- /dev/null +++ b/core/src/main/res/layout/list_item_people_request.xml @@ -0,0 +1,96 @@ +<?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:paddingHorizontal="8dp" + android:paddingVertical="4dp" + tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> + + <com.google.android.material.imageview.ShapeableImageView + android:id="@+id/ivUserImage" + android:layout_width="72dp" + android:layout_height="72dp" + android:scaleType="centerCrop" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent" + tools:background="@color/blue" /> + + <TextView + android:id="@+id/tvUserName" + style="@style/title2" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:ellipsize="end" + android:lines="1" + app:layout_constraintBottom_toTopOf="@id/tvFollowText" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/ivUserImage" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_chainStyle="packed" + tools:text="Android01" /> + + <TextView + android:id="@+id/tvFollowText" + style="@style/subheadline" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:ellipsize="end" + android:lines="1" + android:text="@string/wants_to_follow_you" + android:textSize="13sp" + app:layout_constraintEnd_toEndOf="@id/tvUserName" + app:layout_constraintStart_toStartOf="@id/tvUserName" + app:layout_constraintTop_toBottomOf="@id/tvUserName" /> + + <TextView + android:id="@+id/tvReasonMessage" + style="@style/subheadline" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="4dp" + android:ellipsize="end" + android:maxLines="3" + android:textSize="13sp" + android:visibility="gone" + app:layout_constraintEnd_toEndOf="@id/tvUserName" + app:layout_constraintStart_toStartOf="@id/tvUserName" + app:layout_constraintTop_toBottomOf="@id/tvFollowText" + tools:text="Reason message messagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessage" + tools:visibility="visible" /> + + <com.google.android.material.button.MaterialButton + android:id="@+id/btnAccept" + style="@style/AccentButtonStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="4dp" + android:layout_marginEnd="8dp" + android:padding="0dp" + android:text="@string/accept" + android:textSize="14sp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@id/btnDecline" + app:layout_constraintStart_toEndOf="@id/ivUserImage" + app:layout_constraintTop_toBottomOf="@id/tvReasonMessage" + + /> + + <com.google.android.material.button.MaterialButton + android:id="@+id/btnDecline" + style="@style/NegativeButtonStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="0dp" + android:text="@string/decline" + android:textSize="14sp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/btnAccept" + app:layout_constraintTop_toTopOf="@id/btnAccept" /> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file -- GitLab