Poll display
This commit is contained in:
parent
ce258f1b54
commit
0615aa34f2
|
@ -21,6 +21,7 @@ import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.ImageStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.ImageStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.PhotoStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.PhotoStatusDisplayItem;
|
||||||
|
import org.joinmastodon.android.ui.displayitems.PollOptionStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
|
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
|
||||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
|
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
|
||||||
|
@ -329,6 +330,9 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onPollOptionClick(PollOptionStatusDisplayItem.Holder holder){
|
||||||
|
}
|
||||||
|
|
||||||
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{
|
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{
|
||||||
|
|
||||||
public DisplayItemsAdapter(){
|
public DisplayItemsAdapter(){
|
||||||
|
|
|
@ -17,7 +17,7 @@ public class Poll extends BaseModel{
|
||||||
public boolean multiple;
|
public boolean multiple;
|
||||||
public int votersCount;
|
public int votersCount;
|
||||||
public boolean voted;
|
public boolean voted;
|
||||||
public int[] ownVotes;
|
public List<Integer> ownVotes;
|
||||||
public List<Option> options;
|
public List<Option> options;
|
||||||
public List<Emoji> emojis;
|
public List<Emoji> emojis;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ public class Poll extends BaseModel{
|
||||||
", multiple="+multiple+
|
", multiple="+multiple+
|
||||||
", votersCount="+votersCount+
|
", votersCount="+votersCount+
|
||||||
", voted="+voted+
|
", voted="+voted+
|
||||||
", ownVotes="+Arrays.toString(ownVotes)+
|
", ownVotes="+ownVotes+
|
||||||
", options="+options+
|
", options="+options+
|
||||||
", emojis="+emojis+
|
", emojis="+emojis+
|
||||||
'}';
|
'}';
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package org.joinmastodon.android.ui.displayitems;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
|
import org.joinmastodon.android.model.Poll;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
|
||||||
|
public class PollFooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
|
private Poll poll;
|
||||||
|
|
||||||
|
public PollFooterStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Poll poll){
|
||||||
|
super(parentID, parentFragment);
|
||||||
|
this.poll=poll;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType(){
|
||||||
|
return Type.POLL_FOOTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Holder extends StatusDisplayItem.Holder<PollFooterStatusDisplayItem>{
|
||||||
|
private TextView text;
|
||||||
|
|
||||||
|
public Holder(Activity activity, ViewGroup parent){
|
||||||
|
super(activity, R.layout.display_item_poll_footer, parent);
|
||||||
|
text=(TextView) itemView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(PollFooterStatusDisplayItem item){
|
||||||
|
String text=item.parentFragment.getResources().getQuantityString(R.plurals.x_voters, item.poll.votersCount, item.poll.votersCount);
|
||||||
|
if(item.poll.expiresAt!=null && !item.poll.expired){
|
||||||
|
text+=" · "+UiUtils.formatTimeLeft(itemView.getContext(), item.poll.expiresAt);
|
||||||
|
}else if(item.poll.expired){
|
||||||
|
text+=" · "+item.parentFragment.getString(R.string.poll_closed);
|
||||||
|
}
|
||||||
|
this.text.setText(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
package org.joinmastodon.android.ui.displayitems;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.graphics.drawable.Animatable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
|
import org.joinmastodon.android.model.Poll;
|
||||||
|
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||||
|
|
||||||
|
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||||
|
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||||
|
|
||||||
|
public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
||||||
|
private CharSequence text;
|
||||||
|
private Poll.Option option;
|
||||||
|
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
|
||||||
|
|
||||||
|
public PollOptionStatusDisplayItem(String parentID, Poll poll, Poll.Option option, BaseStatusListFragment parentFragment){
|
||||||
|
super(parentID, parentFragment);
|
||||||
|
this.option=option;
|
||||||
|
text=HtmlParser.parseCustomEmoji(option.title, poll.emojis);
|
||||||
|
emojiHelper.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType(){
|
||||||
|
return Type.POLL_OPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getImageCount(){
|
||||||
|
return emojiHelper.getImageCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImageLoaderRequest getImageRequest(int index){
|
||||||
|
return emojiHelper.getImageRequest(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Holder extends StatusDisplayItem.Holder<PollOptionStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||||
|
private final TextView text;
|
||||||
|
private final View button;
|
||||||
|
|
||||||
|
public Holder(Activity activity, ViewGroup parent){
|
||||||
|
super(activity, R.layout.display_item_poll_option, parent);
|
||||||
|
text=findViewById(R.id.text);
|
||||||
|
button=findViewById(R.id.button);
|
||||||
|
itemView.setOnClickListener(this::onButtonClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(PollOptionStatusDisplayItem item){
|
||||||
|
text.setText(item.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setImage(int index, Drawable image){
|
||||||
|
item.emojiHelper.setImageDrawable(index, image);
|
||||||
|
text.invalidate();
|
||||||
|
if(image instanceof Animatable){
|
||||||
|
((Animatable) image).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearImage(int index){
|
||||||
|
item.emojiHelper.setImageDrawable(index, null);
|
||||||
|
text.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onButtonClick(View v){
|
||||||
|
item.parentFragment.onPollOptionClick(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
import org.joinmastodon.android.model.Account;
|
import org.joinmastodon.android.model.Account;
|
||||||
import org.joinmastodon.android.model.Attachment;
|
import org.joinmastodon.android.model.Attachment;
|
||||||
import org.joinmastodon.android.model.DisplayItemsParent;
|
import org.joinmastodon.android.model.DisplayItemsParent;
|
||||||
|
import org.joinmastodon.android.model.Poll;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||||
|
|
||||||
|
@ -49,6 +50,8 @@ public abstract class StatusDisplayItem{
|
||||||
case PHOTO -> new PhotoStatusDisplayItem.Holder(activity, parent);
|
case PHOTO -> new PhotoStatusDisplayItem.Holder(activity, parent);
|
||||||
case GIFV -> new GifVStatusDisplayItem.Holder(activity, parent);
|
case GIFV -> new GifVStatusDisplayItem.Holder(activity, parent);
|
||||||
case VIDEO -> new VideoStatusDisplayItem.Holder(activity, parent);
|
case VIDEO -> new VideoStatusDisplayItem.Holder(activity, parent);
|
||||||
|
case POLL_OPTION -> new PollOptionStatusDisplayItem.Holder(activity, parent);
|
||||||
|
case POLL_FOOTER -> new PollFooterStatusDisplayItem.Holder(activity, parent);
|
||||||
case FOOTER -> new FooterStatusDisplayItem.Holder(activity, parent);
|
case FOOTER -> new FooterStatusDisplayItem.Holder(activity, parent);
|
||||||
default -> throw new UnsupportedOperationException();
|
default -> throw new UnsupportedOperationException();
|
||||||
};
|
};
|
||||||
|
@ -86,6 +89,12 @@ public abstract class StatusDisplayItem{
|
||||||
photoIndex++;
|
photoIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(statusForContent.poll!=null){
|
||||||
|
for(Poll.Option opt:statusForContent.poll.options){
|
||||||
|
items.add(new PollOptionStatusDisplayItem(parentID, statusForContent.poll, opt, fragment));
|
||||||
|
}
|
||||||
|
items.add(new PollFooterStatusDisplayItem(parentID, fragment, statusForContent.poll));
|
||||||
|
}
|
||||||
items.add(new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID));
|
items.add(new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID));
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +107,6 @@ public abstract class StatusDisplayItem{
|
||||||
VIDEO,
|
VIDEO,
|
||||||
GIFV,
|
GIFV,
|
||||||
AUDIO,
|
AUDIO,
|
||||||
POLL_HEADER,
|
|
||||||
POLL_OPTION,
|
POLL_OPTION,
|
||||||
POLL_FOOTER,
|
POLL_FOOTER,
|
||||||
CARD,
|
CARD,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.joinmastodon.android.ui.displayitems;
|
package org.joinmastodon.android.ui.displayitems;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Fragment;
|
|
||||||
import android.graphics.drawable.Animatable;
|
import android.graphics.drawable.Animatable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -17,11 +16,9 @@ import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||||
public class TextStatusDisplayItem extends StatusDisplayItem{
|
public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||||
private CharSequence text;
|
private CharSequence text;
|
||||||
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
|
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
|
||||||
private Fragment parentFragment;
|
|
||||||
public TextStatusDisplayItem(String parentID, CharSequence text, BaseStatusListFragment parentFragment){
|
public TextStatusDisplayItem(String parentID, CharSequence text, BaseStatusListFragment parentFragment){
|
||||||
super(parentID, parentFragment);
|
super(parentID, parentFragment);
|
||||||
this.text=text;
|
this.text=text;
|
||||||
this.parentFragment=parentFragment;
|
|
||||||
emojiHelper.setText(text);
|
emojiHelper.setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,25 @@ public class UiUtils{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String formatTimeLeft(Context context, Instant instant){
|
||||||
|
long t=instant.toEpochMilli();
|
||||||
|
long now=System.currentTimeMillis();
|
||||||
|
long diff=t-now;
|
||||||
|
if(diff<60_000L){
|
||||||
|
int secs=(int)(diff/1000L);
|
||||||
|
return context.getResources().getQuantityString(R.plurals.x_seconds_left, secs, secs);
|
||||||
|
}else if(diff<3600_000L){
|
||||||
|
int mins=(int)(diff/60_000L);
|
||||||
|
return context.getResources().getQuantityString(R.plurals.x_minutes_left, mins, mins);
|
||||||
|
}else if(diff<3600_000L*24L){
|
||||||
|
int hours=(int)(diff/3600_000L);
|
||||||
|
return context.getResources().getQuantityString(R.plurals.x_hours_left, hours, hours);
|
||||||
|
}else{
|
||||||
|
int days=(int)(diff/(3600_000L*24L));
|
||||||
|
return context.getResources().getQuantityString(R.plurals.x_days_left, days, days);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
public static String abbreviateNumber(int n){
|
public static String abbreviateNumber(int n){
|
||||||
if(n<1000)
|
if(n<1000)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight">
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid android:color="@color/gray_100"/>
|
||||||
|
<corners android:radius="10dp"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</ripple>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="16dp"
|
||||||
|
android:paddingRight="16dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:textAppearance="@style/m3_label_large"
|
||||||
|
android:textColor="@color/gray_800" />
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="16dp"
|
||||||
|
android:paddingRight="16dp"
|
||||||
|
android:paddingTop="5dp"
|
||||||
|
android:paddingBottom="5dp"
|
||||||
|
android:clipToPadding="false">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/button"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:outlineProvider="background"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:background="@drawable/bg_poll_option_clickable"
|
||||||
|
android:duplicateParentState="true"
|
||||||
|
android:layoutDirection="locale">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:src="@drawable/ic_fluent_circle_24_regular"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:textAppearance="@style/m3_title_medium"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
tools:text="scream into void"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
|
@ -100,7 +100,7 @@
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginEnd="56dp"
|
android:layout_marginEnd="56dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:background="@drawable/bg_poll_option"
|
android:background="@drawable/bg_poll_option_clickable"
|
||||||
android:outlineProvider="background"
|
android:outlineProvider="background"
|
||||||
android:elevation="2dp">
|
android:elevation="2dp">
|
||||||
<ImageView
|
<ImageView
|
||||||
|
|
|
@ -87,4 +87,25 @@
|
||||||
<item quantity="other">%d days</item>
|
<item quantity="other">%d days</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="compose_poll_duration">Duration: %s</string>
|
<string name="compose_poll_duration">Duration: %s</string>
|
||||||
|
<plurals name="x_seconds_left">
|
||||||
|
<item quantity="one">%d second left</item>
|
||||||
|
<item quantity="other">%d seconds left</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="x_minutes_left">
|
||||||
|
<item quantity="one">%d minute left</item>
|
||||||
|
<item quantity="other">%d minutes left</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="x_hours_left">
|
||||||
|
<item quantity="one">%d hour left</item>
|
||||||
|
<item quantity="other">%d hours left</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="x_days_left">
|
||||||
|
<item quantity="one">%d day left</item>
|
||||||
|
<item quantity="other">%d days left</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="x_voters">
|
||||||
|
<item quantity="one">%,d voter</item>
|
||||||
|
<item quantity="other">%,d voters</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="poll_closed">Closed</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue