From cf782f039f5b363141877228c911f3d7132a6492 Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Tue, 24 Mar 2020 21:06:58 +0100 Subject: [PATCH] use number of voters instead of votes to calculate poll results (#1733) * adjust poll vote text, votes -> people * use number of voters instead of votes to calculate poll results * fix tests --- .../tusky/adapter/PollAdapter.kt | 12 ++++++--- .../tusky/adapter/StatusBaseViewHolder.java | 16 ++++++++---- .../com/keylesspalace/tusky/entity/Poll.kt | 8 +++++- .../tusky/util/NotificationHelper.java | 2 +- .../tusky/util/StatusViewHelper.kt | 22 +++++++++------- .../tusky/viewdata/PollViewData.kt | 25 +++++++++++-------- app/src/main/res/values/strings.xml | 4 +++ .../com/keylesspalace/tusky/FilterTest.kt | 1 + 8 files changed, 60 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/PollAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/adapter/PollAdapter.kt index 0adc0c371..ea75c16a9 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/PollAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/PollAdapter.kt @@ -26,7 +26,6 @@ import androidx.recyclerview.widget.RecyclerView import com.keylesspalace.tusky.R import com.keylesspalace.tusky.entity.Emoji import com.keylesspalace.tusky.util.CustomEmojiHelper -import com.keylesspalace.tusky.util.HtmlUtils import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.viewdata.PollOptionViewData import com.keylesspalace.tusky.viewdata.buildDescription @@ -36,12 +35,19 @@ class PollAdapter: RecyclerView.Adapter() { private var pollOptions: List = emptyList() private var voteCount: Int = 0 + private var votersCount: Int? = null private var mode = RESULT private var emojis: List = emptyList() - fun setup(options: List, voteCount: Int, emojis: List, mode: Int) { + fun setup( + options: List, + voteCount: Int, + votersCount: Int?, + emojis: List, + mode: Int) { this.pollOptions = options this.voteCount = voteCount + this.votersCount = votersCount this.emojis = emojis this.mode = mode notifyDataSetChanged() @@ -71,7 +77,7 @@ class PollAdapter: RecyclerView.Adapter() { when(mode) { RESULT -> { - val percent = calculatePercent(option.votesCount, voteCount) + val percent = calculatePercent(option.votesCount, votersCount, voteCount) val emojifiedPollOptionText = CustomEmojiHelper.emojifyText(buildDescription(option.title, percent, holder.resultTextView.context), emojis, holder.resultTextView) holder.resultTextView.text = EmojiCompat.get().process(emojifiedPollOptionText) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index ad0e6573d..71156967b 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -869,7 +869,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { List options = poll.getOptions(); for (int i = 0; i < args.length; i++) { if (i < options.size()) { - int percent = PollViewDataKt.calculatePercent(options.get(i).getVotesCount(), poll.getVotesCount()); + int percent = PollViewDataKt.calculatePercent(options.get(i).getVotesCount(), poll.getVotersCount(), poll.getVotesCount()); args[i] = buildDescription(options.get(i).getTitle(), percent, context); } else { args[i] = ""; @@ -912,12 +912,12 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { if (expired || poll.getVoted()) { // no voting possible - pollAdapter.setup(poll.getOptions(), poll.getVotesCount(), emojis, PollAdapter.RESULT); + pollAdapter.setup(poll.getOptions(), poll.getVotesCount(), poll.getVotersCount(), emojis, PollAdapter.RESULT); pollButton.setVisibility(View.GONE); } else { // voting possible - pollAdapter.setup(poll.getOptions(), poll.getVotesCount(), emojis, poll.getMultiple() ? PollAdapter.MULTIPLE : PollAdapter.SINGLE); + pollAdapter.setup(poll.getOptions(), poll.getVotesCount(), poll.getVotersCount(), emojis, poll.getMultiple() ? PollAdapter.MULTIPLE : PollAdapter.SINGLE); pollButton.setVisibility(View.VISIBLE); @@ -944,8 +944,14 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { private CharSequence getPollInfoText(long timestamp, PollViewData poll, StatusDisplayOptions statusDisplayOptions, Context context) { - String votes = numberFormat.format(poll.getVotesCount()); - String votesText = context.getResources().getQuantityString(R.plurals.poll_info_votes, poll.getVotesCount(), votes); + String votesText; + if(poll.getVotersCount() == null) { + String voters = numberFormat.format(poll.getVotesCount()); + votesText = context.getResources().getQuantityString(R.plurals.poll_info_votes, poll.getVotesCount(), voters); + } else { + String voters = numberFormat.format(poll.getVotersCount()); + votesText = context.getResources().getQuantityString(R.plurals.poll_info_people, poll.getVotersCount(), voters); + } CharSequence pollDurationInfo; if (poll.getExpired()) { pollDurationInfo = context.getString(R.string.poll_info_closed); diff --git a/app/src/main/java/com/keylesspalace/tusky/entity/Poll.kt b/app/src/main/java/com/keylesspalace/tusky/entity/Poll.kt index 57361d1b0..02c236c48 100644 --- a/app/src/main/java/com/keylesspalace/tusky/entity/Poll.kt +++ b/app/src/main/java/com/keylesspalace/tusky/entity/Poll.kt @@ -9,6 +9,7 @@ data class Poll( val expired: Boolean, val multiple: Boolean, @SerializedName("votes_count") val votesCount: Int, + @SerializedName("voters_count") val votersCount: Int?, // nullable for compatibility with Pleroma val options: List, val voted: Boolean ) { @@ -22,7 +23,12 @@ data class Poll( } } - return copy(options = newOptions, votesCount = votesCount + choices.size, voted = true) + return copy( + options = newOptions, + votesCount = votesCount + choices.size, + votersCount = votersCount?.plus(1), + voted = true + ) } fun toNewPoll(creationDate: Date) = NewPoll( diff --git a/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java b/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java index 8b526dc57..c98e8b5ca 100644 --- a/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java +++ b/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java @@ -643,7 +643,7 @@ public class NotificationHelper { Poll poll = notification.getStatus().getPoll(); for(PollOption option: poll.getOptions()) { builder.append(buildDescription(option.getTitle(), - PollViewDataKt.calculatePercent(option.getVotesCount(), poll.getVotesCount()), + PollViewDataKt.calculatePercent(option.getVotesCount(), poll.getVotersCount(), poll.getVotesCount()), context)); builder.append('\n'); } diff --git a/app/src/main/java/com/keylesspalace/tusky/util/StatusViewHelper.kt b/app/src/main/java/com/keylesspalace/tusky/util/StatusViewHelper.kt index 840e220e4..98660bc39 100644 --- a/app/src/main/java/com/keylesspalace/tusky/util/StatusViewHelper.kt +++ b/app/src/main/java/com/keylesspalace/tusky/util/StatusViewHelper.kt @@ -24,7 +24,6 @@ import android.widget.ImageView import android.widget.TextView import androidx.annotation.DrawableRes import androidx.appcompat.content.res.AppCompatResources -import androidx.core.content.ContextCompat import com.bumptech.glide.Glide import com.keylesspalace.tusky.R import com.keylesspalace.tusky.entity.Attachment @@ -275,17 +274,22 @@ class StatusViewHelper(private val itemView: View) { private fun getPollInfoText(timestamp: Long, poll: PollViewData, pollDescription: TextView, useAbsoluteTime: Boolean): CharSequence { val context = pollDescription.context - val votes = NumberFormat.getNumberInstance().format(poll.votesCount.toLong()) - val votesText = context.resources.getQuantityString(R.plurals.poll_info_votes, poll.votesCount, votes) - val pollDurationInfo: CharSequence - if (poll.expired) { - pollDurationInfo = context.getString(R.string.poll_info_closed) + + val votesText = if(poll.votersCount == null) { + val votes = NumberFormat.getNumberInstance().format(poll.votesCount.toLong()) + context.resources.getQuantityString(R.plurals.poll_info_votes, poll.votesCount, votes) + } else { + val votes = NumberFormat.getNumberInstance().format(poll.votersCount.toLong()) + context.resources.getQuantityString(R.plurals.poll_info_people, poll.votersCount, votes) + } + val pollDurationInfo = if (poll.expired) { + context.getString(R.string.poll_info_closed) } else { if (useAbsoluteTime) { - pollDurationInfo = context.getString(R.string.poll_info_time_absolute, getAbsoluteTime(poll.expiresAt)) + context.getString(R.string.poll_info_time_absolute, getAbsoluteTime(poll.expiresAt)) } else { val pollDuration = TimestampUtils.formatPollDuration(context, poll.expiresAt!!.time, timestamp) - pollDurationInfo = context.getString(R.string.poll_info_time_relative, pollDuration) + context.getString(R.string.poll_info_time_relative, pollDuration) } } @@ -298,7 +302,7 @@ class StatusViewHelper(private val itemView: View) { for (i in 0 until Status.MAX_POLL_OPTIONS) { if (i < options.size) { - val percent = calculatePercent(options[i].votesCount, poll.votesCount) + val percent = calculatePercent(options[i].votesCount, poll.votersCount, poll.votesCount) val pollOptionText = buildDescription(options[i].title, percent, pollResults[i].context) pollResults[i].text = CustomEmojiHelper.emojifyText(pollOptionText, emojis, pollResults[i]) diff --git a/app/src/main/java/com/keylesspalace/tusky/viewdata/PollViewData.kt b/app/src/main/java/com/keylesspalace/tusky/viewdata/PollViewData.kt index dff0c9f60..729893215 100644 --- a/app/src/main/java/com/keylesspalace/tusky/viewdata/PollViewData.kt +++ b/app/src/main/java/com/keylesspalace/tusky/viewdata/PollViewData.kt @@ -31,6 +31,7 @@ data class PollViewData( val expired: Boolean, val multiple: Boolean, val votesCount: Int, + val votersCount: Int?, val options: List, var voted: Boolean ) @@ -41,10 +42,11 @@ data class PollOptionViewData( var selected: Boolean ) -fun calculatePercent(fraction: Int, total: Int): Int { +fun calculatePercent(fraction: Int, totalVoters: Int?, totalVotes: Int): Int { return if (fraction == 0) { 0 } else { + val total = totalVoters ?: totalVotes (fraction / total.toDouble() * 100).roundToInt() } } @@ -58,20 +60,21 @@ fun buildDescription(title: String, percent: Int, context: Context): Spanned { fun Poll?.toViewData(): PollViewData? { if (this == null) return null return PollViewData( - id, - expiresAt, - expired, - multiple, - votesCount, - options.map { it.toViewData() }, - voted + id = id, + expiresAt = expiresAt, + expired = expired, + multiple = multiple, + votesCount = votesCount, + votersCount = votersCount, + options = options.map { it.toViewData() }, + voted = voted ) } fun PollOption.toViewData(): PollOptionViewData { return PollOptionViewData( - title, - votesCount, - false + title = title, + votesCount = votesCount, + selected = false ) } \ 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 b517db86e..509005654 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -494,6 +494,10 @@ %s vote %s votes + + %s person + %s people + %s left ends at %s closed diff --git a/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt b/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt index 19288499f..8b0c916aa 100644 --- a/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt +++ b/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt @@ -222,6 +222,7 @@ class FilterTest { expired = false, multiple = false, votesCount = 0, + votersCount = 0, options = pollOptions.map { PollOption(it, 0) },