Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/all poll options #5406

Merged
merged 8 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
### ⬆️ Improved

### ✅ Added
- Split poll options on the poll attachment to show a fit nubmer of options and a button to open new view with all options.[#5406](https://github.com/GetStream/stream-chat-android/pull/5406)

### ⚠️ Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2446,6 +2446,10 @@ public abstract interface class io/getstream/chat/android/ui/feature/messages/li
public abstract fun onScrollToBottom ()V
}

public abstract interface class io/getstream/chat/android/ui/feature/messages/list/MessageListView$OnShowAllPollOptionClickListener {
public abstract fun onShowAllPollOptionClick (Lio/getstream/chat/android/models/Message;Lio/getstream/chat/android/models/Poll;)Z
}

public abstract interface class io/getstream/chat/android/ui/feature/messages/list/MessageListView$OnThreadClickListener {
public abstract fun onThreadClick (Lio/getstream/chat/android/models/Message;)Z
}
Expand Down Expand Up @@ -2966,6 +2970,7 @@ public abstract interface class io/getstream/chat/android/ui/feature/messages/li
public abstract fun getMessageRetryListener ()Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$OnMessageRetryListener;
public abstract fun getOnPollCloseClickListener ()Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$OnPollCloseClickListener;
public abstract fun getOnPollOptionClickListener ()Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$OnPollOptionClickListener;
public abstract fun getOnShowAllPollOptionClickListener ()Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$OnShowAllPollOptionClickListener;
public abstract fun getOnViewPollResultClickListener ()Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$OnViewPollResultClickListener;
public abstract fun getReactionViewClickListener ()Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$OnReactionViewClickListener;
public abstract fun getThreadClickListener ()Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$OnThreadClickListener;
Expand Down Expand Up @@ -3292,6 +3297,20 @@ public class io/getstream/chat/android/ui/feature/messages/list/background/Messa
public final class io/getstream/chat/android/ui/feature/messages/list/background/MessageBackgroundFactoryImpl$Companion {
}

public final class io/getstream/chat/android/ui/feature/messages/list/internal/AllPollOptionsDialogFragment : androidx/appcompat/app/AppCompatDialogFragment {
public static final field Companion Lio/getstream/chat/android/ui/feature/messages/list/internal/AllPollOptionsDialogFragment$Companion;
public static final field TAG Ljava/lang/String;
public fun <init> ()V
public fun getTheme ()I
public fun onCreateView (Landroid/view/LayoutInflater;Landroid/view/ViewGroup;Landroid/os/Bundle;)Landroid/view/View;
public fun onDestroyView ()V
public fun onViewCreated (Landroid/view/View;Landroid/os/Bundle;)V
}

public final class io/getstream/chat/android/ui/feature/messages/list/internal/AllPollOptionsDialogFragment$Companion {
public final fun newInstance (Lio/getstream/chat/android/models/Message;)Lio/getstream/chat/android/ui/feature/messages/list/internal/AllPollOptionsDialogFragment;
}

public class io/getstream/chat/android/ui/feature/messages/list/options/message/DefaultMessageOptionItemsFactory : io/getstream/chat/android/ui/feature/messages/list/options/message/MessageOptionItemsFactory {
public fun <init> (Landroid/content/Context;)V
public fun createMessageOptionItems (Lio/getstream/chat/android/models/Message;Lio/getstream/chat/android/models/User;ZLjava/util/Set;Lio/getstream/chat/android/ui/feature/messages/list/MessageListViewStyle;)Ljava/util/List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ import io.getstream.chat.android.ui.feature.messages.list.adapter.internal.Messa
import io.getstream.chat.android.ui.feature.messages.list.adapter.viewholder.attachment.AttachmentFactoryManager
import io.getstream.chat.android.ui.feature.messages.list.background.MessageBackgroundFactory
import io.getstream.chat.android.ui.feature.messages.list.background.MessageBackgroundFactoryImpl
import io.getstream.chat.android.ui.feature.messages.list.internal.AllPollOptionsDialogFragment
import io.getstream.chat.android.ui.feature.messages.list.internal.HiddenMessageListItemPredicate
import io.getstream.chat.android.ui.feature.messages.list.internal.MessageListScrollHelper
import io.getstream.chat.android.ui.feature.messages.list.options.message.MessageOptionItem
Expand Down Expand Up @@ -591,6 +592,14 @@ public class MessageListView : ConstraintLayout {
false
}
private val defaultOnPollOptionClickListener = OnPollOptionClickListener { _, _, _ -> false }
private val defaultOnShowAllPollOptionClickListener = OnShowAllPollOptionClickListener { message, _ ->
val fm = context.getFragmentManager() ?: return@OnShowAllPollOptionClickListener false
aleksandar-apostolov marked this conversation as resolved.
Show resolved Hide resolved
fm.let { fragmentManager ->
AllPollOptionsDialogFragment.newInstance(message)
.show(fragmentManager, AllPollOptionsDialogFragment.TAG)
}
true
}
private val defaultOnPollCloseClickListener = OnPollCloseClickListener { false }
private val defaultOnViewPollResultClickListener = OnViewPollResultClickListener { false }

Expand All @@ -606,6 +615,7 @@ public class MessageListView : ConstraintLayout {
giphySendListener = defaultGiphySendListener,
linkClickListener = defaultLinkClickListener,
onPollOptionClickListener = defaultOnPollOptionClickListener,
onShowAllPollOptionClickListener = defaultOnShowAllPollOptionClickListener,
onPollCloseClickListener = defaultOnPollCloseClickListener,
onViewPollResultClickListener = defaultOnViewPollResultClickListener,
)
Expand Down Expand Up @@ -2190,6 +2200,10 @@ public class MessageListView : ConstraintLayout {
public fun onPollOptionClick(message: Message, poll: Poll, option: Option): Boolean
}

public fun interface OnShowAllPollOptionClickListener {
public fun onShowAllPollOptionClick(message: Message, poll: Poll): Boolean
}

public fun interface OnPollCloseClickListener {
public fun onPollCloseClick(poll: Poll): Boolean
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnMess
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnPollCloseClickListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnPollOptionClickListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnReactionViewClickListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnShowAllPollOptionClickListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnThreadClickListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnUnreadLabelReachedListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnUserClickListener
Expand Down Expand Up @@ -72,6 +73,7 @@ public sealed interface MessageListListeners {
public val linkClickListener: OnLinkClickListener
public val unreadLabelReachedListener: OnUnreadLabelReachedListener
public val onPollOptionClickListener: OnPollOptionClickListener
public val onShowAllPollOptionClickListener: OnShowAllPollOptionClickListener
public val onPollCloseClickListener: OnPollCloseClickListener
public val onViewPollResultClickListener: OnViewPollResultClickListener
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnMess
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnPollCloseClickListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnPollOptionClickListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnReactionViewClickListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnShowAllPollOptionClickListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnThreadClickListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnUnreadLabelReachedListener
import io.getstream.chat.android.ui.feature.messages.list.MessageListView.OnUserClickListener
Expand All @@ -45,6 +46,7 @@ internal class MessageListListenerContainerImpl(
linkClickListener: OnLinkClickListener = OnLinkClickListener(EmptyFunctions.ONE_PARAM),
onUnreadLabelReachedListener: OnUnreadLabelReachedListener = OnUnreadLabelReachedListener { },
onPollOptionClickListener: OnPollOptionClickListener,
onShowAllPollOptionClickListener: OnShowAllPollOptionClickListener,
onPollCloseClickListener: OnPollCloseClickListener,
onViewPollResultClickListener: OnViewPollResultClickListener,
) : MessageListListeners {
Expand Down Expand Up @@ -149,6 +151,14 @@ internal class MessageListListenerContainerImpl(
}
}

override var onShowAllPollOptionClickListener: OnShowAllPollOptionClickListener by ListenerDelegate(
onShowAllPollOptionClickListener,
) { realListener ->
OnShowAllPollOptionClickListener { message, poll ->
realListener().onShowAllPollOptionClick(message, poll)
}
}

override var onPollCloseClickListener: OnPollCloseClickListener by ListenerDelegate(
onPollCloseClickListener,
) { realListener ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import io.getstream.chat.android.ui.databinding.StreamUiItemPollAnswerBinding
import io.getstream.chat.android.ui.databinding.StreamUiItemPollCloseBinding
import io.getstream.chat.android.ui.databinding.StreamUiItemPollHeaderBinding
import io.getstream.chat.android.ui.databinding.StreamUiItemPollResultsBinding
import io.getstream.chat.android.ui.databinding.StreamUiItemPollShowAllOptionsBinding
import io.getstream.chat.android.ui.utils.extensions.createStreamThemeWrapper
import io.getstream.chat.android.ui.utils.extensions.streamThemeInflater
import io.getstream.log.taggedLogger
Expand All @@ -47,6 +48,7 @@ internal class PollView : RecyclerView {
var onOptionClick: ((Option) -> Unit) = { _ -> }
var onClosePollClick: ((Poll) -> Unit) = { _ -> }
var onViewPollResultsClick: ((Poll) -> Unit) = { _ -> }
var onShowAllPollOptionClick: (() -> Unit) = { }

constructor(context: Context) : this(context, null, 0)

Expand Down Expand Up @@ -76,46 +78,59 @@ internal class PollView : RecyclerView {
onOptionClick = { option -> onOptionClick(option) },
onClosePollClick = { onClosePollClick(poll) },
onViewPollResultsClick = { onViewPollResultsClick(poll) },
onShowAllOptionsClick = { onShowAllPollOptionClick() },
)
adapter = pollAdapter
}

val pollItems = mutableListOf<PollItem>()
pollItems.add(PollItem.Header(poll.name, poll.description))
pollItems.addAll(
poll.options.map { option ->
PollItem.Answer(
option = option,
votes = poll.getVotes(option)
.takeUnless { poll.votingVisibility == VotingVisibility.ANONYMOUS }
?: emptyList(),
voteCount = poll.voteCountsByOption[option.id] ?: 0,
isVotedByUser = poll.ownVotes.any { it.optionId == option.id },
totalVotes = poll.voteCountsByOption.values.sum(),
closed = poll.closed,
isWinner = poll.voteCountsByOption[option.id] == poll.voteCountsByOption.values.maxOrNull(),
)
},
poll.options
.take(MAX_OPTIONS)
.map { option ->
PollItem.Answer(
option = option,
votes = poll.getVotes(option)
.takeUnless { poll.votingVisibility == VotingVisibility.ANONYMOUS }
?: emptyList(),
voteCount = poll.voteCountsByOption[option.id] ?: 0,
isVotedByUser = poll.ownVotes.any { it.optionId == option.id },
totalVotes = poll.voteCountsByOption.values.sum(),
closed = poll.closed,
isWinner = poll.voteCountsByOption[option.id] == poll.voteCountsByOption.values.maxOrNull(),
)
},
)
PollItem.ShowAllOptions
.takeIf { poll.options.size > MAX_OPTIONS }
?.takeUnless { poll.closed }
?.let { pollItems.add(it) }
PollItem.ViewResults.takeUnless { poll.ownVotes.isEmpty() }
PollItem.Close.takeIf { isMine && !poll.closed }
?.let { pollItems.add(it) }

pollAdapter.submitList(pollItems)
}

private companion object {
private const val MAX_OPTIONS = 10
}
}

private class PollAdapter(
private val onOptionClick: (Option) -> Unit,
private val onClosePollClick: () -> Unit,
private val onViewPollResultsClick: () -> Unit,
private val onShowAllOptionsClick: () -> Unit,
) : ListAdapter<PollItem, PollItemViewHolder<out PollItem>>(PollItemDiffCallback) {

companion object {
private const val VIEW_TYPE_HEADER = 1
private const val VIEW_TYPE_ANSWER = 2
private const val VIEW_TYPE_CLOSE = 3
private const val VIEW_TYPE_RESULTS = 4
private const val VIEW_TYPE_SHOW_ALL_OPTIONS = 5
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PollItemViewHolder<out PollItem> {
Expand All @@ -135,6 +150,10 @@ private class PollAdapter(
StreamUiItemPollResultsBinding.inflate(parent.streamThemeInflater, parent, false),
onViewPollResultsClick,
)
VIEW_TYPE_SHOW_ALL_OPTIONS -> ShowAllOptionsViewHolder(
StreamUiItemPollShowAllOptionsBinding.inflate(parent.streamThemeInflater, parent, false),
onShowAllOptionsClick,
)
else -> throw IllegalArgumentException("Unknown view type: $viewType")
}
}
Expand All @@ -144,6 +163,7 @@ private class PollAdapter(
is PollItem.Answer -> VIEW_TYPE_ANSWER
PollItem.Close -> VIEW_TYPE_CLOSE
PollItem.ViewResults -> VIEW_TYPE_RESULTS
PollItem.ShowAllOptions -> VIEW_TYPE_SHOW_ALL_OPTIONS
}

override fun onBindViewHolder(holder: PollItemViewHolder<out PollItem>, position: Int) {
Expand Down Expand Up @@ -179,6 +199,7 @@ private sealed class PollItem {
) : PollItem()

data object Close : PollItem()
data object ShowAllOptions : PollItem()
data object ViewResults : PollItem()
}

Expand Down Expand Up @@ -261,6 +282,15 @@ private class CloseViewHolder(
}
}

private class ShowAllOptionsViewHolder(
private val binding: StreamUiItemPollShowAllOptionsBinding,
private val onShowAllOptions: () -> Unit,
) : PollItemViewHolder<PollItem.ShowAllOptions>(binding) {
override fun bind(pollItem: PollItem.ShowAllOptions) {
binding.root.setOnClickListener { onShowAllOptions() }
}
}

private class ViewResultsViewHolder(
private val binding: StreamUiItemPollResultsBinding,
private val onViewPollResultsClick: () -> Unit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public class PollViewHolder(
binding.pollView.onViewPollResultsClick = {
messageListListeners?.onViewPollResultClickListener?.onViewPollResultClick(poll)
}
binding.pollView.onShowAllPollOptionClick = {
messageListListeners?.onShowAllPollOptionClickListener?.onShowAllPollOptionClick(data.message, poll)
}
}
}
}
Loading
Loading