Poll voting

This commit is contained in:
Grishka
2022-02-16 03:58:13 +03:00
parent f7ddac6ae6
commit 1a238d79e0
18 changed files with 345 additions and 31 deletions

View File

@@ -16,24 +16,31 @@ import android.widget.ImageView;
import android.widget.Toolbar;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.polls.SubmitPollVote;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.DisplayItemsParent;
import org.joinmastodon.android.model.Poll;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.ImageStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.PhotoStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.PollFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.PollOptionStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
@@ -334,11 +341,86 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
return 0;
}
public void onItemClick(String id){
public abstract void onItemClick(String id);
protected void updatePoll(String itemID, Poll poll){
int firstOptionIndex=-1, footerIndex=-1;
int i=0;
for(StatusDisplayItem item:displayItems){
if(item.parentID.equals(itemID)){
if(item instanceof PollOptionStatusDisplayItem && firstOptionIndex==-1){
firstOptionIndex=i;
}else if(item instanceof PollFooterStatusDisplayItem){
footerIndex=i;
break;
}
}
i++;
}
if(firstOptionIndex==-1 || footerIndex==-1)
throw new IllegalStateException("Can't find all poll items in displayItems");
List<StatusDisplayItem> pollItems=displayItems.subList(firstOptionIndex, footerIndex+1);
int prevSize=pollItems.size();
pollItems.clear();
StatusDisplayItem.buildPollItems(itemID, this, poll, pollItems);
if(prevSize!=pollItems.size()){
adapter.notifyItemRangeRemoved(firstOptionIndex, prevSize);
adapter.notifyItemRangeInserted(firstOptionIndex, pollItems.size());
}else{
adapter.notifyItemRangeChanged(firstOptionIndex, pollItems.size());
}
}
public void onPollOptionClick(PollOptionStatusDisplayItem.Holder holder){
Poll poll=holder.getItem().poll;
Poll.Option option=holder.getItem().option;
if(poll.multiple){
if(poll.selectedOptions==null)
poll.selectedOptions=new ArrayList<>();
if(poll.selectedOptions.contains(option)){
poll.selectedOptions.remove(option);
holder.itemView.setSelected(false);
}else{
poll.selectedOptions.add(option);
holder.itemView.setSelected(true);
}
for(int i=0;i<list.getChildCount();i++){
RecyclerView.ViewHolder vh=list.getChildViewHolder(list.getChildAt(i));
if(vh instanceof PollFooterStatusDisplayItem.Holder){
PollFooterStatusDisplayItem.Holder footer=(PollFooterStatusDisplayItem.Holder) vh;
if(footer.getItemID().equals(holder.getItemID())){
footer.rebind();
break;
}
}
}
}else{
submitPollVote(holder.getItemID(), poll.id, Collections.singletonList(poll.options.indexOf(option)));
}
}
public void onPollVoteButtonClick(PollFooterStatusDisplayItem.Holder holder){
Poll poll=holder.getItem().poll;
submitPollVote(holder.getItemID(), poll.id, poll.selectedOptions.stream().map(opt->poll.options.indexOf(opt)).collect(Collectors.toList()));
}
protected void submitPollVote(String parentID, String pollID, List<Integer> choices){
if(refreshing)
return;
new SubmitPollVote(pollID, choices)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Poll result){
updatePoll(parentID, result);
}
@Override
public void onError(ErrorResponse error){
error.showToast(getActivity());
}
})
.wrapProgress(getActivity(), R.string.loading, false)
.exec(accountID);
}
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{

View File

@@ -5,6 +5,7 @@ import android.app.Activity;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.notifications.GetNotifications;
import org.joinmastodon.android.model.Notification;
import org.joinmastodon.android.model.Poll;
import org.joinmastodon.android.ui.displayitems.ReblogOrReplyLineStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
@@ -67,4 +68,26 @@ public class NotificationsFragment extends BaseStatusListFragment<Notification>{
if(!getArguments().getBoolean("noAutoLoad") && !loaded && !dataLoading)
loadData();
}
@Override
public void onItemClick(String id){
}
@Override
protected void updatePoll(String itemID, Poll poll){
Notification notification=getNotificationByID(itemID);
if(notification==null || notification.status==null)
return;
notification.status.poll=poll;
super.updatePoll(itemID, poll);
}
private Notification getNotificationByID(String id){
for(Notification n:data){
if(n.id.equals(id))
return n;
}
return null;
}
}

View File

@@ -6,8 +6,11 @@ import com.squareup.otto.Subscribe;
import org.joinmastodon.android.E;
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
import org.joinmastodon.android.model.Poll;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.PollFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.PollOptionStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
import org.parceler.Parcels;
@@ -41,13 +44,7 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>{
@Override
public void onItemClick(String id){
Status status=null;
for(Status s:data){
if(s.id.equals(id)){
status=s.getContentStatus();
break;
}
}
Status status=getContentStatusByID(id);
if(status==null)
return;
Bundle args=new Bundle();
@@ -58,6 +55,15 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>{
Nav.go(getActivity(), ThreadFragment.class, args);
}
@Override
protected void updatePoll(String itemID, Poll poll){
Status status=getContentStatusByID(itemID);
if(status==null)
return;
status.poll=poll;
super.updatePoll(itemID, poll);
}
@Subscribe
public void onStatusCountersUpdated(StatusCountersUpdatedEvent ev){
for(Status s:data){
@@ -80,4 +86,13 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>{
}
}
}
protected Status getContentStatusByID(String id){
for(Status s:data){
if(s.id.equals(id)){
return s.getContentStatus();
}
}
return null;
}
}