Highlight your own votes when displaying poll results (#2242)
* Highlight your own votes when displaying poll results * Unbreak tests * Add a checkmark to the description of self-voted options
This commit is contained in:
parent
45598cf047
commit
d07c1b098e
12 changed files with 47 additions and 15 deletions
|
@ -18,8 +18,10 @@ package com.keylesspalace.tusky.adapter
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.emoji.text.EmojiCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.databinding.ItemPollBinding
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
import com.keylesspalace.tusky.util.BindingHolder
|
||||
|
@ -85,13 +87,19 @@ class PollAdapter : RecyclerView.Adapter<BindingHolder<ItemPollBinding>>() {
|
|||
when (mode) {
|
||||
RESULT -> {
|
||||
val percent = calculatePercent(option.votesCount, votersCount, voteCount)
|
||||
val emojifiedPollOptionText = buildDescription(option.title, percent, resultTextView.context)
|
||||
val emojifiedPollOptionText = buildDescription(option.title, percent, option.voted, resultTextView.context)
|
||||
.emojify(emojis, resultTextView, animateEmojis)
|
||||
resultTextView.text = EmojiCompat.get().process(emojifiedPollOptionText)
|
||||
|
||||
val level = percent * 100
|
||||
val optionColor = if (option.voted) {
|
||||
R.color.colorBackgroundHighlight
|
||||
} else {
|
||||
R.color.colorBackgroundAccent
|
||||
}
|
||||
|
||||
resultTextView.background.level = level
|
||||
resultTextView.background.setTint(ContextCompat.getColor(resultTextView.context, optionColor))
|
||||
resultTextView.setOnClickListener(resultClickListener)
|
||||
}
|
||||
SINGLE -> {
|
||||
|
|
|
@ -889,7 +889,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
|||
for (int i = 0; i < args.length; i++) {
|
||||
if (i < options.size()) {
|
||||
int percent = PollViewDataKt.calculatePercent(options.get(i).getVotesCount(), poll.getVotersCount(), poll.getVotesCount());
|
||||
args[i] = buildDescription(options.get(i).getTitle(), percent, context);
|
||||
args[i] = buildDescription(options.get(i).getTitle(), percent, options.get(i).getVoted(), context);
|
||||
} else {
|
||||
args[i] = "";
|
||||
}
|
||||
|
|
|
@ -659,9 +659,12 @@ public class NotificationHelper {
|
|||
StringBuilder builder = new StringBuilder(notification.getStatus().getContent());
|
||||
builder.append('\n');
|
||||
Poll poll = notification.getStatus().getPoll();
|
||||
for(PollOption option: poll.getOptions()) {
|
||||
List<PollOption> options = poll.getOptions();
|
||||
for(int i = 0; i < options.size(); ++i) {
|
||||
PollOption option = options.get(i);
|
||||
builder.append(buildDescription(option.getTitle(),
|
||||
PollViewDataKt.calculatePercent(option.getVotesCount(), poll.getVotersCount(), poll.getVotesCount()),
|
||||
poll.getOwnVotes() != null && poll.getOwnVotes().contains(i),
|
||||
context));
|
||||
builder.append('\n');
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ data class Poll(
|
|||
@SerializedName("votes_count") val votesCount: Int,
|
||||
@SerializedName("voters_count") val votersCount: Int?, // nullable for compatibility with Pleroma
|
||||
val options: List<PollOption>,
|
||||
val voted: Boolean
|
||||
val voted: Boolean,
|
||||
@SerializedName("own_votes") val ownVotes: List<Int>?
|
||||
) {
|
||||
|
||||
fun votedCopy(choices: List<Int>): Poll {
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.view.View
|
|||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.bumptech.glide.Glide
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
|
@ -310,13 +311,19 @@ class StatusViewHelper(private val itemView: View) {
|
|||
if (i < options.size) {
|
||||
val percent = calculatePercent(options[i].votesCount, poll.votersCount, poll.votesCount)
|
||||
|
||||
val pollOptionText = buildDescription(options[i].title, percent, pollResults[i].context)
|
||||
val pollOptionText = buildDescription(options[i].title, percent, options[i].voted, pollResults[i].context)
|
||||
pollResults[i].text = pollOptionText.emojify(emojis, pollResults[i], animateEmojis)
|
||||
pollResults[i].visibility = View.VISIBLE
|
||||
|
||||
val level = percent * 100
|
||||
val optionColor = if (options[i].voted) {
|
||||
R.color.colorBackgroundHighlight
|
||||
} else {
|
||||
R.color.colorBackgroundAccent
|
||||
}
|
||||
|
||||
pollResults[i].background.level = level
|
||||
pollResults[i].background.setTint(ContextCompat.getColor(pollResults[i].context, optionColor))
|
||||
} else {
|
||||
pollResults[i].visibility = View.GONE
|
||||
}
|
||||
|
|
|
@ -39,7 +39,8 @@ data class PollViewData(
|
|||
data class PollOptionViewData(
|
||||
val title: String,
|
||||
var votesCount: Int,
|
||||
var selected: Boolean
|
||||
var selected: Boolean,
|
||||
var voted: Boolean
|
||||
)
|
||||
|
||||
fun calculatePercent(fraction: Int, totalVoters: Int?, totalVotes: Int): Int {
|
||||
|
@ -51,10 +52,14 @@ fun calculatePercent(fraction: Int, totalVoters: Int?, totalVotes: Int): Int {
|
|||
}
|
||||
}
|
||||
|
||||
fun buildDescription(title: String, percent: Int, context: Context): Spanned {
|
||||
return SpannableStringBuilder(context.getString(R.string.poll_percent_format, percent).parseAsHtml())
|
||||
.append(" ")
|
||||
.append(title)
|
||||
fun buildDescription(title: String, percent: Int, voted: Boolean, context: Context): Spanned {
|
||||
val builder = SpannableStringBuilder(context.getString(R.string.poll_percent_format, percent).parseAsHtml())
|
||||
if (voted) {
|
||||
builder.append(" ✓ ")
|
||||
} else {
|
||||
builder.append(" ")
|
||||
}
|
||||
return builder.append(title)
|
||||
}
|
||||
|
||||
fun Poll?.toViewData(): PollViewData? {
|
||||
|
@ -66,15 +71,16 @@ fun Poll?.toViewData(): PollViewData? {
|
|||
multiple = multiple,
|
||||
votesCount = votesCount,
|
||||
votersCount = votersCount,
|
||||
options = options.map { it.toViewData() },
|
||||
voted = voted
|
||||
options = options.mapIndexed { index, option -> option.toViewData(ownVotes?.contains(index) == true) },
|
||||
voted = voted,
|
||||
)
|
||||
}
|
||||
|
||||
fun PollOption.toViewData(): PollOptionViewData {
|
||||
fun PollOption.toViewData(voted: Boolean): PollOptionViewData {
|
||||
return PollOptionViewData(
|
||||
title = title,
|
||||
votesCount = votesCount,
|
||||
selected = false
|
||||
selected = false,
|
||||
voted = voted
|
||||
)
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<color name="iconColor">@color/tusky_grey_70</color>
|
||||
|
||||
<color name="colorBackgroundAccent">@color/tusky_grey_30</color>
|
||||
<color name="colorBackgroundHighlight">@color/tusky_grey_50</color>
|
||||
<color name="dividerColor">@color/tusky_grey_25</color>
|
||||
|
||||
<color name="favoriteButtonActiveColor">@color/tusky_orange</color>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
<!--Themed Attributes-->
|
||||
<attr name="colorBackgroundAccent" format="reference|color" />
|
||||
<attr name="colorBackgroundHighlight" format="reference|color" />
|
||||
<attr name="textColorDisabled" format="reference|color" />
|
||||
<attr name="iconColor" format="reference|color" />
|
||||
<attr name="windowBackgroundColor" format="reference|color" />
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
|
||||
<item name="android:colorBackground">@color/colorBackground</item>
|
||||
<item name="colorBackgroundAccent">@color/colorBackgroundAccent</item>
|
||||
<item name="colorBackgroundHighlight">@color/colorBackgroundHighlight</item>
|
||||
<item name="windowBackgroundColor">@color/windowBackground</item>
|
||||
|
||||
<item name="android:textColorPrimary">@color/textColorPrimary</item>
|
||||
|
@ -142,6 +143,7 @@
|
|||
<item name="colorSurface">@color/tusky_grey_10</item>
|
||||
|
||||
<item name="iconColor">@color/tusky_grey_40</item>
|
||||
<item name="colorBackgroundHighlight">@color/tusky_grey_40</item>
|
||||
<item name="colorBackgroundAccent">@color/tusky_grey_20</item>
|
||||
|
||||
<item name="dividerColor">@color/tusky_grey_10</item>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<color name="iconColor">@color/tusky_grey_50</color>
|
||||
|
||||
<color name="colorBackgroundAccent">@color/tusky_grey_70</color>
|
||||
<color name="colorBackgroundHighlight">@color/tusky_grey_50</color>
|
||||
<color name="dividerColor">@color/tusky_grey_80</color>
|
||||
|
||||
<color name="favoriteButtonActiveColor">@color/tusky_orange_light</color>
|
||||
|
|
|
@ -173,7 +173,8 @@ class FilterTest {
|
|||
options = pollOptions.map {
|
||||
PollOption(it, 0)
|
||||
},
|
||||
voted = false
|
||||
voted = false,
|
||||
ownVotes = null
|
||||
)
|
||||
} else null,
|
||||
card = null
|
||||
|
|
|
@ -697,6 +697,7 @@ class TimelineViewModelTest {
|
|||
votesCount = 1,
|
||||
voted = false,
|
||||
options = listOf(PollOption("1", 1), PollOption("2", 2)),
|
||||
ownVotes = null
|
||||
)
|
||||
val status4 = makeStatus("4").copy(poll = poll)
|
||||
val status3 = makeStatus("3")
|
||||
|
|
Loading…
Reference in a new issue