Unlimited number of poll options (#1340)
* implement unlimited number of poll options * fixes * extract percent calculation into function so it can be used anywhere * add license header
This commit is contained in:
parent
cacac782ca
commit
6a0d7014f5
123
app/src/main/java/com/keylesspalace/tusky/adapter/PollAdapter.kt
Normal file
123
app/src/main/java/com/keylesspalace/tusky/adapter/PollAdapter.kt
Normal file
@ -0,0 +1,123 @@
|
||||
/* Copyright 2019 Conny Duck
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.CheckBox
|
||||
import android.widget.RadioButton
|
||||
import android.widget.TextView
|
||||
import androidx.emoji.text.EmojiCompat
|
||||
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.calculatePercent
|
||||
|
||||
class PollAdapter: RecyclerView.Adapter<PollViewHolder>() {
|
||||
|
||||
private var pollOptions: List<PollOptionViewData> = emptyList()
|
||||
private var voteCount: Int = 0
|
||||
private var mode = RESULT
|
||||
private var emojis: List<Emoji> = emptyList()
|
||||
|
||||
fun setup(options: List<PollOptionViewData>, voteCount: Int, emojis: List<Emoji>, mode: Int) {
|
||||
this.pollOptions = options
|
||||
this.voteCount = voteCount
|
||||
this.emojis = emojis
|
||||
this.mode = mode
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun getSelected() : List<Int> {
|
||||
return pollOptions.filter { it.selected }
|
||||
.map { pollOptions.indexOf(it) }
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PollViewHolder {
|
||||
return PollViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_poll, parent, false))
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return pollOptions.size
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PollViewHolder, position: Int) {
|
||||
|
||||
val option = pollOptions[position]
|
||||
|
||||
holder.resultTextView.visible(mode == RESULT)
|
||||
holder.radioButton.visible(mode == SINGLE)
|
||||
holder.checkBox.visible(mode == MULTIPLE)
|
||||
|
||||
when(mode) {
|
||||
RESULT -> {
|
||||
val percent = calculatePercent(option.votesCount, voteCount)
|
||||
|
||||
val pollOptionText = holder.resultTextView.context.getString(R.string.poll_option_format, percent, option.title)
|
||||
|
||||
val emojifiedPollOptionText = CustomEmojiHelper.emojifyText(HtmlUtils.fromHtml(pollOptionText), emojis, holder.resultTextView)
|
||||
holder.resultTextView.text = EmojiCompat.get().process(emojifiedPollOptionText)
|
||||
|
||||
val level = percent * 100
|
||||
|
||||
holder.resultTextView.background.level = level
|
||||
|
||||
}
|
||||
SINGLE -> {
|
||||
val emojifiedPollOptionText = CustomEmojiHelper.emojifyString(option.title, emojis, holder.radioButton)
|
||||
holder.radioButton.text = EmojiCompat.get().process(emojifiedPollOptionText)
|
||||
holder.radioButton.isChecked = option.selected
|
||||
holder.radioButton.setOnClickListener {
|
||||
pollOptions.forEachIndexed { index, pollOption ->
|
||||
pollOption.selected = index == holder.adapterPosition
|
||||
notifyItemChanged(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
MULTIPLE -> {
|
||||
val emojifiedPollOptionText = CustomEmojiHelper.emojifyString(option.title, emojis, holder.checkBox)
|
||||
holder.checkBox.text = EmojiCompat.get().process(emojifiedPollOptionText)
|
||||
holder.checkBox.isChecked = option.selected
|
||||
holder.checkBox.setOnCheckedChangeListener { _, isChecked ->
|
||||
pollOptions[holder.adapterPosition].selected = isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val RESULT = 0
|
||||
const val SINGLE = 1
|
||||
const val MULTIPLE = 2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class PollViewHolder(view: View): RecyclerView.ViewHolder(view) {
|
||||
|
||||
val resultTextView: TextView = view.findViewById(R.id.status_poll_option_result)
|
||||
val radioButton: RadioButton = view.findViewById(R.id.status_poll_radio_button)
|
||||
val checkBox: CheckBox = view.findViewById(R.id.status_poll_checkbox)
|
||||
|
||||
}
|
@ -7,11 +7,8 @@ import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ToggleButton;
|
||||
@ -19,7 +16,8 @@ import android.widget.ToggleButton;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.emoji.text.EmojiCompat;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
@ -28,8 +26,6 @@ import com.keylesspalace.tusky.entity.Attachment;
|
||||
import com.keylesspalace.tusky.entity.Attachment.Focus;
|
||||
import com.keylesspalace.tusky.entity.Attachment.MetaData;
|
||||
import com.keylesspalace.tusky.entity.Emoji;
|
||||
import com.keylesspalace.tusky.entity.Poll;
|
||||
import com.keylesspalace.tusky.entity.PollOption;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.util.CustomEmojiHelper;
|
||||
@ -39,13 +35,14 @@ import com.keylesspalace.tusky.util.ImageLoadingHelper;
|
||||
import com.keylesspalace.tusky.util.LinkHelper;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
import com.keylesspalace.tusky.view.MediaPreviewImageView;
|
||||
import com.keylesspalace.tusky.viewdata.PollOptionViewData;
|
||||
import com.keylesspalace.tusky.viewdata.PollViewData;
|
||||
import com.keylesspalace.tusky.viewdata.PollViewDataKt;
|
||||
import com.keylesspalace.tusky.viewdata.StatusViewData;
|
||||
import com.mikepenz.iconics.utils.Utils;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -74,20 +71,19 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
private View sensitiveMediaShow;
|
||||
protected TextView[] mediaLabels;
|
||||
private ToggleButton contentWarningButton;
|
||||
protected ImageView avatarInset;
|
||||
private ImageView avatarInset;
|
||||
|
||||
public ImageView avatar;
|
||||
public TextView timestampInfo;
|
||||
public TextView content;
|
||||
public TextView contentWarningDescription;
|
||||
|
||||
private TextView[] pollResults;
|
||||
private RecyclerView pollOptions;
|
||||
private TextView pollDescription;
|
||||
private RadioGroup pollRadioGroup;
|
||||
private RadioButton[] pollRadioOptions;
|
||||
private CheckBox[] pollCheckboxOptions;
|
||||
private Button pollButton;
|
||||
|
||||
private PollAdapter pollAdapter;
|
||||
|
||||
private boolean useAbsoluteTime;
|
||||
private SimpleDateFormat shortSdf;
|
||||
private SimpleDateFormat longSdf;
|
||||
@ -135,31 +131,15 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
contentWarningButton = itemView.findViewById(R.id.status_content_warning_button);
|
||||
avatarInset = itemView.findViewById(R.id.status_avatar_inset);
|
||||
|
||||
pollResults = new TextView[]{
|
||||
itemView.findViewById(R.id.status_poll_option_result_0),
|
||||
itemView.findViewById(R.id.status_poll_option_result_1),
|
||||
itemView.findViewById(R.id.status_poll_option_result_2),
|
||||
itemView.findViewById(R.id.status_poll_option_result_3)
|
||||
};
|
||||
|
||||
pollOptions = itemView.findViewById(R.id.status_poll_options);
|
||||
pollDescription = itemView.findViewById(R.id.status_poll_description);
|
||||
|
||||
pollRadioGroup = itemView.findViewById(R.id.status_poll_radio_group);
|
||||
pollRadioOptions = new RadioButton[] {
|
||||
pollRadioGroup.findViewById(R.id.status_poll_radio_button_0),
|
||||
pollRadioGroup.findViewById(R.id.status_poll_radio_button_1),
|
||||
pollRadioGroup.findViewById(R.id.status_poll_radio_button_2),
|
||||
pollRadioGroup.findViewById(R.id.status_poll_radio_button_3)
|
||||
};
|
||||
pollCheckboxOptions = new CheckBox[] {
|
||||
itemView.findViewById(R.id.status_poll_checkbox_0),
|
||||
itemView.findViewById(R.id.status_poll_checkbox_1),
|
||||
itemView.findViewById(R.id.status_poll_checkbox_2),
|
||||
itemView.findViewById(R.id.status_poll_checkbox_3)
|
||||
};
|
||||
|
||||
pollButton = itemView.findViewById(R.id.status_poll_button);
|
||||
|
||||
pollAdapter = new PollAdapter();
|
||||
pollOptions.setAdapter(pollAdapter);
|
||||
pollOptions.setLayoutManager(new LinearLayoutManager(pollOptions.getContext()));
|
||||
((DefaultItemAnimator) pollOptions.getItemAnimator()).setSupportsChangeAnimations(false);
|
||||
|
||||
this.useAbsoluteTime = useAbsoluteTime;
|
||||
shortSdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
|
||||
longSdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault());
|
||||
@ -795,15 +775,15 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private CharSequence getPollDescription(Context context,
|
||||
@NonNull StatusViewData.Concrete status) {
|
||||
Poll poll = status.getPoll();
|
||||
PollViewData poll = status.getPoll();
|
||||
if (poll == null) {
|
||||
return "";
|
||||
} else {
|
||||
CharSequence[] args = new CharSequence[5];
|
||||
List<PollOption> options = poll.getOptions();
|
||||
List<PollOptionViewData> options = poll.getOptions();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (i < options.size()) {
|
||||
int percent = options.get(i).getPercent(poll.getVotesCount());
|
||||
int percent = PollViewDataKt.calculatePercent(options.get(i).getVotesCount(), poll.getVotesCount());
|
||||
args[i] = HtmlUtils.fromHtml(context.getString(
|
||||
R.string.poll_option_format,
|
||||
percent,
|
||||
@ -835,19 +815,15 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
}
|
||||
}
|
||||
|
||||
protected void setupPoll(Poll poll, List<Emoji> emojis, StatusActionListener listener) {
|
||||
protected void setupPoll(PollViewData poll, List<Emoji> emojis, StatusActionListener listener) {
|
||||
if (poll == null) {
|
||||
for (TextView pollResult : pollResults) {
|
||||
pollResult.setVisibility(View.GONE);
|
||||
}
|
||||
pollDescription.setVisibility(View.GONE);
|
||||
pollRadioGroup.setVisibility(View.GONE);
|
||||
|
||||
for (CheckBox checkBox : pollCheckboxOptions) {
|
||||
checkBox.setVisibility(View.GONE);
|
||||
}
|
||||
pollOptions.setVisibility(View.GONE);
|
||||
|
||||
pollDescription.setVisibility(View.GONE);
|
||||
|
||||
pollButton.setVisibility(View.GONE);
|
||||
|
||||
} else {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
|
||||
@ -855,25 +831,49 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
Context context = pollDescription.getContext();
|
||||
|
||||
pollOptions.setVisibility(View.VISIBLE);
|
||||
|
||||
if (expired || poll.getVoted()) {
|
||||
// no voting possible
|
||||
setupPollResult(poll, emojis);
|
||||
pollAdapter.setup(poll.getOptions(), poll.getVotesCount(), emojis, PollAdapter.RESULT);
|
||||
|
||||
pollButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
// voting possible
|
||||
setupPollVoting(poll, emojis, listener);
|
||||
pollAdapter.setup(poll.getOptions(), poll.getVotesCount(), emojis, poll.getMultiple() ? PollAdapter.MULTIPLE : PollAdapter.SINGLE);
|
||||
|
||||
pollButton.setVisibility(View.VISIBLE);
|
||||
|
||||
pollButton.setOnClickListener(v -> {
|
||||
|
||||
int position = getAdapterPosition();
|
||||
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
|
||||
List<Integer> pollResult = pollAdapter.getSelected();
|
||||
|
||||
if(!pollResult.isEmpty()) {
|
||||
listener.onVoteInPoll(position, pollResult);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
pollDescription.setVisibility(View.VISIBLE);
|
||||
pollDescription.setText(getPollInfoText(timestamp, poll, context));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private CharSequence getPollInfoText(long timestamp, Poll poll, Context context) {
|
||||
private CharSequence getPollInfoText(long timestamp, PollViewData poll, Context context) {
|
||||
String votes = numberFormat.format(poll.getVotesCount());
|
||||
String votesText = context.getResources().getQuantityString(R.plurals.poll_info_votes, poll.getVotesCount(), votes);
|
||||
CharSequence pollDurationInfo;
|
||||
if (poll.getExpired()) {
|
||||
pollDurationInfo = context.getString(R.string.poll_info_closed);
|
||||
} else if (poll.getExpiresAt() == null) {
|
||||
return votesText;
|
||||
} else {
|
||||
if (useAbsoluteTime) {
|
||||
pollDurationInfo = context.getString(R.string.poll_info_time_absolute, getAbsoluteTime(poll.getExpiresAt()));
|
||||
@ -886,129 +886,4 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
return pollDescription.getContext().getString(R.string.poll_info_format, votesText, pollDurationInfo);
|
||||
}
|
||||
|
||||
private void setupPollResult(Poll poll, List<Emoji> emojis) {
|
||||
List<PollOption> options = poll.getOptions();
|
||||
|
||||
for(int i = 0; i < Status.MAX_POLL_OPTIONS; i++) {
|
||||
if(i < options.size()) {
|
||||
int percent = options.get(i).getPercent(poll.getVotesCount());
|
||||
|
||||
String pollOptionText = pollResults[i].getContext().getString(R.string.poll_option_format, percent, options.get(i).getTitle());
|
||||
pollResults[i].setText(CustomEmojiHelper.emojifyText(HtmlUtils.fromHtml(pollOptionText), emojis, pollResults[i]));
|
||||
pollResults[i].setVisibility(View.VISIBLE);
|
||||
|
||||
int level = percent * 100;
|
||||
|
||||
pollResults[i].getBackground().setLevel(level);
|
||||
|
||||
} else {
|
||||
pollResults[i].setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
pollRadioGroup.setVisibility(View.GONE);
|
||||
|
||||
for(CheckBox checkBox: pollCheckboxOptions) {
|
||||
checkBox.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
pollButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void setupPollVoting(Poll poll, List<Emoji> emojis, StatusActionListener listener) {
|
||||
List<PollOption> options = poll.getOptions();
|
||||
|
||||
pollButton.setVisibility(View.VISIBLE);
|
||||
|
||||
for(TextView pollResult: pollResults) {
|
||||
pollResult.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if(poll.getMultiple()) {
|
||||
|
||||
pollRadioGroup.setVisibility(View.GONE);
|
||||
|
||||
for(int i = 0; i < Status.MAX_POLL_OPTIONS; i++) {
|
||||
if(i < options.size()) {
|
||||
CharSequence emojifiedPollOptionText = CustomEmojiHelper.emojifyString(options.get(i).getTitle(), emojis, pollCheckboxOptions[i]);
|
||||
emojifiedPollOptionText = EmojiCompat.get().process(emojifiedPollOptionText);
|
||||
pollCheckboxOptions[i].setText(emojifiedPollOptionText);
|
||||
pollCheckboxOptions[i].setVisibility(View.VISIBLE);
|
||||
pollCheckboxOptions[i].setChecked(false);
|
||||
} else {
|
||||
pollCheckboxOptions[i].setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
pollButton.setOnClickListener(v -> {
|
||||
|
||||
int position = getAdapterPosition();
|
||||
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
|
||||
List<Integer> pollResult = new ArrayList<>(options.size());
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (pollCheckboxOptions[i].isChecked()) {
|
||||
pollResult.add(i);
|
||||
}
|
||||
}
|
||||
if (pollResult.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
listener.onVoteInPoll(position, pollResult);
|
||||
}
|
||||
|
||||
});
|
||||
} else {
|
||||
|
||||
for(CheckBox pollCheckbox: pollCheckboxOptions) {
|
||||
pollCheckbox.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
pollRadioGroup.setVisibility(View.VISIBLE);
|
||||
pollRadioGroup.clearCheck();
|
||||
|
||||
for(int i = 0; i < Status.MAX_POLL_OPTIONS; i++) {
|
||||
if(i < options.size()) {
|
||||
CharSequence emojifiedPollOptionText = CustomEmojiHelper.emojifyString(options.get(i).getTitle(), emojis, pollRadioOptions[i]);
|
||||
emojifiedPollOptionText = EmojiCompat.get().process(emojifiedPollOptionText);
|
||||
pollRadioOptions[i].setText(emojifiedPollOptionText);
|
||||
pollRadioOptions[i].setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
pollRadioOptions[i].setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
pollButton.setOnClickListener(v -> {
|
||||
|
||||
int position = getAdapterPosition();
|
||||
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
|
||||
int selectedRadioButtonIndex;
|
||||
switch (pollRadioGroup.getCheckedRadioButtonId()) {
|
||||
case R.id.status_poll_radio_button_0:
|
||||
selectedRadioButtonIndex = 0;
|
||||
break;
|
||||
case R.id.status_poll_radio_button_1:
|
||||
selectedRadioButtonIndex = 1;
|
||||
break;
|
||||
case R.id.status_poll_radio_button_2:
|
||||
selectedRadioButtonIndex = 2;
|
||||
break;
|
||||
case R.id.status_poll_radio_button_3:
|
||||
selectedRadioButtonIndex = 3;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
listener.onVoteInPoll(position, Collections.singletonList(selectedRadioButtonIndex));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import com.keylesspalace.tusky.entity.Attachment;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.util.ImageLoadingHelper;
|
||||
import com.keylesspalace.tusky.util.SmartLengthInputFilter;
|
||||
import com.keylesspalace.tusky.viewdata.PollViewDataKt;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -109,7 +110,7 @@ public class ConversationViewHolder extends StatusBaseViewHolder {
|
||||
|
||||
setAvatars(conversation.getAccounts());
|
||||
|
||||
setupPoll(status.getPoll(), status.getEmojis(), listener);
|
||||
setupPoll(PollViewDataKt.toViewData(status.getPoll()), status.getEmojis(), listener);
|
||||
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ import com.keylesspalace.tusky.interfaces.LinkListener
|
||||
import com.keylesspalace.tusky.util.*
|
||||
import com.keylesspalace.tusky.util.StatusViewHelper.Companion.COLLAPSE_INPUT_FILTER
|
||||
import com.keylesspalace.tusky.util.StatusViewHelper.Companion.NO_INPUT_FILTER
|
||||
import com.keylesspalace.tusky.viewdata.toViewData
|
||||
import kotlinx.android.synthetic.main.item_report_status.view.*
|
||||
import java.util.*
|
||||
|
||||
@ -72,7 +73,7 @@ class StatusViewHolder(itemView: View,
|
||||
viewState.isMediaShow(status.id, status.sensitive),
|
||||
mediaViewHeight)
|
||||
|
||||
statusViewHelper.setupPollReadonly(status.poll, status.emojis, useAbsoluteTime)
|
||||
statusViewHelper.setupPollReadonly(status.poll.toViewData(), status.emojis, useAbsoluteTime)
|
||||
setCreatedAt(status.createdAt)
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ package com.keylesspalace.tusky.entity
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
data class Poll(
|
||||
val id: String,
|
||||
@ -31,12 +30,4 @@ data class Poll(
|
||||
data class PollOption(
|
||||
val title: String,
|
||||
@SerializedName("votes_count") val votesCount: Int
|
||||
) {
|
||||
fun getPercent(totalVotes: Int): Int {
|
||||
return if (votesCount == 0) {
|
||||
0
|
||||
} else {
|
||||
(votesCount / totalVotes.toDouble() * 100).roundToInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
@ -27,6 +27,9 @@ import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
@ -36,9 +39,6 @@ import androidx.core.app.TaskStackBuilder;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.text.BidiFormatter;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.FutureTarget;
|
||||
@ -55,6 +55,7 @@ import com.keylesspalace.tusky.entity.PollOption;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.receiver.NotificationClearBroadcastReceiver;
|
||||
import com.keylesspalace.tusky.receiver.SendStatusBroadcastReceiver;
|
||||
import com.keylesspalace.tusky.viewdata.PollViewDataKt;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
@ -626,7 +627,7 @@ public class NotificationHelper {
|
||||
builder.append('\n');
|
||||
Poll poll = notification.getStatus().getPoll();
|
||||
for(PollOption option: poll.getOptions()) {
|
||||
int percent = option.getPercent(poll.getVotesCount());
|
||||
int percent = PollViewDataKt.calculatePercent(option.getVotesCount(), poll.getVotesCount());
|
||||
CharSequence optionText = HtmlUtils.fromHtml(context.getString(R.string.poll_option_format, percent, option.getTitle()));
|
||||
builder.append(optionText);
|
||||
builder.append('\n');
|
||||
|
@ -27,12 +27,14 @@ import com.bumptech.glide.Glide
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
import com.keylesspalace.tusky.entity.Poll
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.view.MediaPreviewImageView
|
||||
import com.keylesspalace.tusky.viewdata.PollViewData
|
||||
import com.keylesspalace.tusky.viewdata.calculatePercent
|
||||
import java.text.NumberFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
|
||||
class StatusViewHelper(private val itemView: View) {
|
||||
interface MediaPreviewListener {
|
||||
@ -85,7 +87,7 @@ class StatusViewHelper(private val itemView: View) {
|
||||
|
||||
val mediaPreviewUnloadedId = ThemeUtils.getDrawableId(context, R.attr.media_preview_unloaded_drawable, android.R.color.black)
|
||||
|
||||
val n = Math.min(attachments.size, Status.MAX_MEDIA_ATTACHMENTS)
|
||||
val n = min(attachments.size, Status.MAX_MEDIA_ATTACHMENTS)
|
||||
|
||||
for (i in 0 until n) {
|
||||
val previewUrl = attachments[i].previewUrl
|
||||
@ -229,7 +231,7 @@ class StatusViewHelper(private val itemView: View) {
|
||||
}
|
||||
}
|
||||
|
||||
fun setupPollReadonly(poll: Poll?, emojis: List<Emoji>, useAbsoluteTime: Boolean) {
|
||||
fun setupPollReadonly(poll: PollViewData?, emojis: List<Emoji>, useAbsoluteTime: Boolean) {
|
||||
val pollResults = listOf<TextView>(
|
||||
itemView.findViewById(R.id.status_poll_option_result_0),
|
||||
itemView.findViewById(R.id.status_poll_option_result_1),
|
||||
@ -254,7 +256,7 @@ class StatusViewHelper(private val itemView: View) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPollInfoText(timestamp: Long, poll: Poll, pollDescription: TextView, useAbsoluteTime: Boolean): CharSequence {
|
||||
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)
|
||||
@ -274,12 +276,12 @@ class StatusViewHelper(private val itemView: View) {
|
||||
}
|
||||
|
||||
|
||||
private fun setupPollResult(poll: Poll, emojis: List<Emoji>, pollResults: List<TextView>) {
|
||||
private fun setupPollResult(poll: PollViewData, emojis: List<Emoji>, pollResults: List<TextView>) {
|
||||
val options = poll.options
|
||||
|
||||
for (i in 0 until Status.MAX_POLL_OPTIONS) {
|
||||
if (i < options.size) {
|
||||
val percent = options[i].getPercent(poll.votesCount)
|
||||
val percent = calculatePercent(options[i].votesCount, poll.votesCount)
|
||||
|
||||
val pollOptionText = pollResults[i].context.getString(R.string.poll_option_format, percent, options[i].title)
|
||||
pollResults[i].text = CustomEmojiHelper.emojifyText(HtmlUtils.fromHtml(pollOptionText), emojis, pollResults[i])
|
||||
|
@ -0,0 +1,66 @@
|
||||
/* Copyright 2019 Conny Duck
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.viewdata
|
||||
|
||||
import com.keylesspalace.tusky.entity.Poll
|
||||
import com.keylesspalace.tusky.entity.PollOption
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
data class PollViewData(
|
||||
val id: String,
|
||||
val expiresAt: Date?,
|
||||
val expired: Boolean,
|
||||
val multiple: Boolean,
|
||||
val votesCount: Int,
|
||||
val options: List<PollOptionViewData>,
|
||||
var voted: Boolean
|
||||
)
|
||||
|
||||
data class PollOptionViewData(
|
||||
val title: String,
|
||||
var votesCount: Int,
|
||||
var selected: Boolean
|
||||
)
|
||||
|
||||
fun calculatePercent(fraction: Int, total: Int): Int {
|
||||
return if (fraction == 0) {
|
||||
0
|
||||
} else {
|
||||
(fraction / total.toDouble() * 100).roundToInt()
|
||||
}
|
||||
}
|
||||
|
||||
fun Poll?.toViewData(): PollViewData? {
|
||||
if (this == null) return null
|
||||
return PollViewData(
|
||||
id,
|
||||
expiresAt,
|
||||
expired,
|
||||
multiple,
|
||||
votesCount,
|
||||
options.map { it.toViewData() },
|
||||
voted
|
||||
)
|
||||
}
|
||||
|
||||
fun PollOption.toViewData(): PollOptionViewData {
|
||||
return PollOptionViewData(
|
||||
title,
|
||||
votesCount,
|
||||
false
|
||||
)
|
||||
}
|
@ -89,7 +89,7 @@ public abstract class StatusViewData {
|
||||
private final boolean isCollapsible; /** Whether the status meets the requirement to be collapse */
|
||||
final boolean isCollapsed; /** Whether the status is shown partially or fully */
|
||||
@Nullable
|
||||
private final Poll poll;
|
||||
private final PollViewData poll;
|
||||
private final boolean isBot;
|
||||
|
||||
public Concrete(String id, Spanned content, boolean reblogged, boolean favourited,
|
||||
@ -99,7 +99,7 @@ public abstract class StatusViewData {
|
||||
Date createdAt, int reblogsCount, int favouritesCount, @Nullable String inReplyToId,
|
||||
@Nullable Status.Mention[] mentions, String senderId, boolean rebloggingEnabled,
|
||||
Status.Application application, List<Emoji> statusEmojis, List<Emoji> accountEmojis, @Nullable Card card,
|
||||
boolean isCollapsible, boolean isCollapsed, @Nullable Poll poll, boolean isBot) {
|
||||
boolean isCollapsible, boolean isCollapsed, @Nullable PollViewData poll, boolean isBot) {
|
||||
|
||||
this.id = id;
|
||||
if (Build.VERSION.SDK_INT == 23) {
|
||||
@ -273,7 +273,7 @@ public abstract class StatusViewData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Poll getPoll() {
|
||||
public PollViewData getPoll() {
|
||||
return poll;
|
||||
}
|
||||
|
||||
@ -418,7 +418,7 @@ public abstract class StatusViewData {
|
||||
private Card card;
|
||||
private boolean isCollapsible; /** Whether the status meets the requirement to be collapsed */
|
||||
private boolean isCollapsed; /** Whether the status is shown partially or fully */
|
||||
private Poll poll;
|
||||
private PollViewData poll;
|
||||
private boolean isBot;
|
||||
|
||||
public Builder() {
|
||||
@ -617,7 +617,7 @@ public abstract class StatusViewData {
|
||||
}
|
||||
|
||||
public Builder setPoll(Poll poll) {
|
||||
this.poll = poll;
|
||||
this.poll = PollViewDataKt.toViewData(poll);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -382,171 +382,16 @@
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_0"
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/status_poll_options"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:nestedScrollingEnabled="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_preview_container"
|
||||
tools:text="40%" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_0"
|
||||
tools:text="10%" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_1"
|
||||
tools:text="20%" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_2"
|
||||
tools:text="30%" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/status_poll_radio_group"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_3">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_0"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 2" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 3" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 4" />
|
||||
</RadioGroup>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_0"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_radio_group"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_0"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_1"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_2"
|
||||
tools:text="Option 1" />
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_preview_container" />
|
||||
|
||||
<!-- using AppCompatButton because we don't want the inflater to turn it into a MaterialButton -->
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
@ -565,7 +410,7 @@
|
||||
android:text="@string/poll_vote"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_3" />
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_options" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_poll_description"
|
||||
|
42
app/src/main/res/layout/item_poll.xml
Normal file
42
app/src/main/res/layout/item_poll.xml
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout 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.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
tools:text="40%" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 1" />
|
||||
|
||||
</FrameLayout>
|
@ -366,171 +366,16 @@
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_0"
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/status_poll_options"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:nestedScrollingEnabled="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_preview_container"
|
||||
tools:text="40%" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_0"
|
||||
tools:text="10%" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_1"
|
||||
tools:text="20%" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_2"
|
||||
tools:text="30%" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/status_poll_radio_group"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_3">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_0"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 2" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 3" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 4" />
|
||||
</RadioGroup>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_0"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_radio_group"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_0"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_1"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_2"
|
||||
tools:text="Option 1" />
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_preview_container" />
|
||||
|
||||
<!-- using AppCompatButton because we don't want the inflater to turn it into a MaterialButton -->
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
@ -549,7 +394,7 @@
|
||||
android:text="@string/poll_vote"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_3" />
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_options" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_poll_description"
|
||||
|
@ -381,172 +381,16 @@
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_0"
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/status_poll_options"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:nestedScrollingEnabled="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_preview_container"
|
||||
tools:text="40%" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_0"
|
||||
tools:text="10%" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_1"
|
||||
tools:text="20%" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/status_poll_option_result_3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/poll_option_background"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_2"
|
||||
tools:text="30%" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/status_poll_radio_group"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_option_result_3">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_0"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 2" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 3" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/status_poll_radio_button_3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
tools:text="Option 4" />
|
||||
</RadioGroup>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_0"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_radio_group"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_0"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_1"
|
||||
tools:text="Option 1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/status_poll_checkbox_3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:buttonTint="?attr/compound_button_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_2"
|
||||
tools:text="Option 1" />
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_preview_container" />
|
||||
|
||||
<!-- using AppCompatButton because we don't want the inflater to turn it into a MaterialButton -->
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
@ -565,7 +409,7 @@
|
||||
android:text="@string/poll_vote"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_checkbox_3" />
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_options" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_poll_description"
|
||||
|
Loading…
Reference in New Issue
Block a user