package me.ccrama.redditslide.Adapters;
/**
* Created by ccrama on 3/22/2015.
*/
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.afollestad.materialdialogs.AlertDialogWrapper;
import com.cocosw.bottomsheet.BottomSheet;
import net.dean.jraw.ApiException;
import net.dean.jraw.managers.AccountManager;
import net.dean.jraw.managers.ModerationManager;
import net.dean.jraw.models.Comment;
import net.dean.jraw.models.CommentNode;
import net.dean.jraw.models.Contribution;
import net.dean.jraw.models.DistinguishedStatus;
import net.dean.jraw.models.PublicContribution;
import net.dean.jraw.models.Submission;
import net.dean.jraw.models.VoteDirection;
import java.util.List;
import java.util.Map;
import me.ccrama.redditslide.ActionStates;
import me.ccrama.redditslide.Activities.Profile;
import me.ccrama.redditslide.Activities.SubredditView;
import me.ccrama.redditslide.Activities.Website;
import me.ccrama.redditslide.Authentication;
import me.ccrama.redditslide.Hidden;
import me.ccrama.redditslide.OpenRedditLink;
import me.ccrama.redditslide.R;
import me.ccrama.redditslide.Reddit;
import me.ccrama.redditslide.SettingValues;
import me.ccrama.redditslide.SubmissionViews.PopulateSubmissionViewHolder;
import me.ccrama.redditslide.TimeUtils;
import me.ccrama.redditslide.UserSubscriptions;
import me.ccrama.redditslide.Views.CreateCardView;
import me.ccrama.redditslide.Visuals.Palette;
import me.ccrama.redditslide.util.LogUtil;
import me.ccrama.redditslide.util.OnSingleClickListener;
import me.ccrama.redditslide.util.SubmissionParser;
public class ModeratorAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements BaseAdapter {
public static final int COMMENT = 1;
private final int SPACER = 6;
public static final int MESSAGE = 2;
public static final int POST = 3;
public final Activity mContext;
private final RecyclerView listView;
public ModeratorPosts dataSet;
public ModeratorAdapter(Activity mContext, ModeratorPosts dataSet, RecyclerView listView) {
this.mContext = mContext;
this.listView = listView;
this.dataSet = dataSet;
}
@Override
public void setError(Boolean b) {
listView.setAdapter(new ErrorAdapter());
}
@Override
public void undoSetError() {
listView.setAdapter(this);
}
@Override
public int getItemViewType(int position) {
if (position == 0 && !dataSet.posts.isEmpty()) {
return SPACER;
} else if (!dataSet.posts.isEmpty()) {
position -= 1;
}
if (dataSet.posts.get(position).getFullName().startsWith("t1"))//IS COMMENT
return COMMENT;
if (dataSet.posts.get(position).getFullName().startsWith("t4"))//IS MESSAGE
return MESSAGE;
return POST;
}
public class SpacerViewHolder extends RecyclerView.ViewHolder {
public SpacerViewHolder(View itemView) {
super(itemView);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
if (i == SPACER) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.spacer, viewGroup, false);
return new SpacerViewHolder(v);
} else if (i == MESSAGE) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.top_level_message, viewGroup, false);
return new MessageViewHolder(v);
}
if (i == COMMENT) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.profile_comment, viewGroup, false);
return new ProfileCommentViewHolder(v);
} else {
View v = CreateCardView.CreateView(viewGroup);
return new SubmissionViewHolder(v);
}
}
public class AsyncSave extends AsyncTask<Submission, Void, Void> {
View v;
public AsyncSave(View v) {
this.v = v;
}
@Override
protected Void doInBackground(Submission... submissions) {
try {
if (ActionStates.isSaved(submissions[0])) {
new AccountManager(Authentication.reddit).unsave(submissions[0]);
final Snackbar s = Snackbar.make(v, R.string.submission_info_unsaved, Snackbar.LENGTH_SHORT);
mContext.runOnUiThread(new Runnable() {
@Override
public void run() {
View view = s.getView();
TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text);
tv.setTextColor(Color.WHITE);
s.show();
}
});
submissions[0].saved = false;
v = null;
} else {
new AccountManager(Authentication.reddit).save(submissions[0]);
final Snackbar s = Snackbar.make(v, R.string.submission_info_saved, Snackbar.LENGTH_SHORT);
mContext.runOnUiThread(new Runnable() {
@Override
public void run() {
View view = s.getView();
TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text);
tv.setTextColor(Color.WHITE);
s.show();
}
});
submissions[0].saved = true;
v = null;
}
} catch (Exception e) {
return null;
}
return null;
}
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder firstHold, final int pos) {
int i = pos != 0 ? pos - 1 : pos;
if (firstHold instanceof SubmissionViewHolder) {
SubmissionViewHolder holder = (SubmissionViewHolder) firstHold;
final Submission submission = (Submission) dataSet.posts.get(i);
CreateCardView.resetColorCard(holder.itemView);
CreateCardView.colorCard(submission.getSubredditName().toLowerCase(), holder.itemView, "no_subreddit", false);
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
LayoutInflater inflater = mContext.getLayoutInflater();
final View dialoglayout = inflater.inflate(R.layout.postmenu, null);
AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(mContext);
final TextView title = (TextView) dialoglayout.findViewById(R.id.title);
title.setText(Html.fromHtml(submission.getTitle()));
((TextView) dialoglayout.findViewById(R.id.userpopup)).setText("/u/" + submission.getAuthor());
((TextView) dialoglayout.findViewById(R.id.subpopup)).setText("/r/" + submission.getSubredditName());
dialoglayout.findViewById(R.id.sidebar).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(mContext, Profile.class);
i.putExtra(Profile.EXTRA_PROFILE, submission.getAuthor());
mContext.startActivity(i);
}
});
dialoglayout.findViewById(R.id.wiki).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(mContext, SubredditView.class);
i.putExtra(SubredditView.EXTRA_SUBREDDIT, submission.getSubredditName());
mContext.startActivity(i);
}
});
dialoglayout.findViewById(R.id.save).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (submission.isSaved()) {
((TextView) dialoglayout.findViewById(R.id.savedtext)).setText(R.string.submission_save);
} else {
((TextView) dialoglayout.findViewById(R.id.savedtext)).setText(R.string.submission_post_saved);
}
new AsyncSave(firstHold.itemView).execute(submission);
}
});
dialoglayout.findViewById(R.id.copy).setVisibility(View.GONE);
if (submission.isSaved()) {
((TextView) dialoglayout.findViewById(R.id.savedtext)).setText(R.string.submission_post_saved);
}
dialoglayout.findViewById(R.id.gild).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String urlString = "https://reddit.com" + submission.getPermalink();
Intent i = new Intent(mContext, Website.class);
i.putExtra(Website.EXTRA_URL, urlString);
mContext.startActivity(i);
}
});
dialoglayout.findViewById(R.id.share).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (submission.isSelfPost())
Reddit.defaultShareText(submission.getTitle(), "https://reddit.com" + submission.getPermalink(), mContext);
else {
new BottomSheet.Builder(mContext)
.title(R.string.submission_share_title)
.grid()
.sheet(R.menu.share_menu)
.listener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case R.id.reddit_url:
Reddit.defaultShareText(submission.getTitle(), "https://reddit.com" + submission.getPermalink(), mContext);
break;
case R.id.link_url:
Reddit.defaultShareText(submission.getTitle(), submission.getUrl(), mContext);
break;
}
}
}).show();
}
}
});
if (!Authentication.isLoggedIn || !Authentication.didOnline) {
dialoglayout.findViewById(R.id.save).setVisibility(View.GONE);
dialoglayout.findViewById(R.id.gild).setVisibility(View.GONE);
}
title.setBackgroundColor(Palette.getColor(submission.getSubredditName()));
builder.setView(dialoglayout);
final Dialog d = builder.show();
dialoglayout.findViewById(R.id.hide).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final int pos = dataSet.posts.indexOf(submission);
final Contribution old = dataSet.posts.get(pos);
dataSet.posts.remove(submission);
notifyItemRemoved(pos + 1);
d.dismiss();
Hidden.setHidden(old);
Snackbar s = Snackbar.make(listView, R.string.submission_info_hidden, Snackbar.LENGTH_LONG).setAction(R.string.btn_undo, new View.OnClickListener() {
@Override
public void onClick(View v) {
dataSet.posts.add(pos, (PublicContribution) old);
notifyItemInserted(pos + 1);
Hidden.undoHidden(old);
}
});
View view = s.getView();
TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text);
tv.setTextColor(Color.WHITE);
s.show();
}
});
return true;
}
});
new PopulateSubmissionViewHolder().populateSubmissionViewHolder(holder, submission, mContext, false, false, dataSet.posts, listView, false, false, null, null);
final ImageView hideButton = (ImageView) holder.itemView.findViewById(R.id.hide);
if (hideButton != null) {
hideButton.setVisibility(View.GONE);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String url = "www.reddit.com" + submission.getPermalink();
url = url.replace("?ref=search_posts", "");
new OpenRedditLink(mContext, url);
}
});
} else if (firstHold instanceof ProfileCommentViewHolder) {
//IS COMMENT
final ProfileCommentViewHolder holder = (ProfileCommentViewHolder) firstHold;
final Comment comment = (Comment) dataSet.posts.get(i);
holder.score.setText(comment.getScore() + " " + mContext.getResources().getQuantityString(R.plurals.points, comment.getScore()));
if (Authentication.isLoggedIn) {
if (ActionStates.getVoteDirection(comment) == VoteDirection.UPVOTE) {
holder.score.setTextColor(mContext.getResources().getColor(R.color.md_orange_500));
} else if (ActionStates.getVoteDirection(comment) == VoteDirection.DOWNVOTE) {
holder.score.setTextColor(mContext.getResources().getColor(R.color.md_blue_500));
} else {
holder.score.setTextColor(holder.time.getCurrentTextColor());
}
}
String spacer = mContext.getString(R.string.submission_properties_seperator);
SpannableStringBuilder titleString = new SpannableStringBuilder();
String timeAgo = TimeUtils.getTimeAgo(comment.getCreated().getTime(), mContext);
String time = ((timeAgo == null || timeAgo.isEmpty()) ? "just now" : timeAgo); //some users were crashing here
time = time + (((comment.getEditDate() != null) ? " (edit " + TimeUtils.getTimeAgo(comment.getEditDate().getTime(), mContext) + ")" : ""));
titleString.append(time);
titleString.append(spacer);
{
final ImageView mod = (ImageView) holder.itemView.findViewById(R.id.mod);
try {
if (UserSubscriptions.modOf.contains(comment.getSubredditName())) {
//todo
mod.setVisibility(View.GONE);
} else {
mod.setVisibility(View.GONE);
}
} catch (Exception e) {
Log.d(LogUtil.getTag(), "Error loading mod " + e.toString());
}
}
if (UserSubscriptions.modOf != null && UserSubscriptions.modOf.contains(
comment.getSubredditName().toLowerCase())) {
holder.itemView.findViewById(R.id.mod).setVisibility(View.VISIBLE);
final Map<String, Integer> reports = comment.getUserReports();
final Map<String, String> reports2 = comment.getModeratorReports();
if (reports.size() + reports2.size() > 0) {
((ImageView) holder.itemView.findViewById(R.id.mod)).setColorFilter(
ContextCompat.getColor(mContext, R.color.md_red_300),
PorterDuff.Mode.SRC_ATOP);
} else {
int[] attrs = new int[]{R.attr.tint};
TypedArray ta = mContext.obtainStyledAttributes(attrs);
int color = ta.getColor(0, Color.WHITE);
((ImageView)holder.itemView.findViewById(R.id.mod)).setColorFilter(color,
PorterDuff.Mode.SRC_ATOP);
ta.recycle();
}
holder.itemView.findViewById(R.id.mod).setOnClickListener(new OnSingleClickListener() {
@Override
public void onSingleClick(View v) {
showModBottomSheet(mContext,
comment, holder, reports, reports2);
}
});
} else {
holder.itemView.findViewById(R.id.mod).setVisibility(View.GONE);
}
if (comment.getSubredditName() != null) {
String subname = comment.getSubredditName();
SpannableStringBuilder subreddit = new SpannableStringBuilder("/r/" + subname);
if ((SettingValues.colorSubName && Palette.getColor(subname) != Palette.getDefaultColor())) {
subreddit.setSpan(new ForegroundColorSpan(Palette.getColor(subname)), 0, subreddit.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
subreddit.setSpan(new StyleSpan(Typeface.BOLD), 0, subreddit.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
titleString.append(subreddit);
}
holder.time.setText(titleString);
setViews(comment.getDataNode().get("body_html").asText(), comment.getSubredditName(), holder);
if (comment.getTimesGilded() > 0) {
holder.gild.setVisibility(View.VISIBLE);
((TextView) holder.gild).setText(Integer.toString(comment.getTimesGilded()));
} else if (holder.gild.getVisibility() == View.VISIBLE)
holder.gild.setVisibility(View.GONE);
if (comment.getSubmissionTitle() != null)
holder.title.setText(Html.fromHtml(comment.getSubmissionTitle()));
else
holder.title.setText(Html.fromHtml(comment.getAuthor()));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new OpenRedditLink(mContext, comment.getSubmissionId(), comment.getSubredditName(), comment.getId());
}
});
holder.content.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new OpenRedditLink(mContext, comment.getSubmissionId(), comment.getSubredditName(), comment.getId());
}
});
}
if (firstHold instanceof SpacerViewHolder) {
firstHold.itemView.findViewById(R.id.height).setLayoutParams(new LinearLayout.LayoutParams(firstHold.itemView.getWidth(), mContext.findViewById(R.id.header).getHeight()));
}
}
private void setViews(String rawHTML, String subredditName, ProfileCommentViewHolder holder) {
if (rawHTML.isEmpty()) {
return;
}
List<String> blocks = SubmissionParser.getBlocks(rawHTML);
int startIndex = 0;
// the <div class="md"> case is when the body contains a table or code block first
if (!blocks.get(0).equals("<div class=\"md\">")) {
holder.content.setVisibility(View.VISIBLE);
holder.content.setTextHtml(blocks.get(0), subredditName);
startIndex = 1;
} else {
holder.content.setText("");
holder.content.setVisibility(View.GONE);
}
if (blocks.size() > 1) {
if (startIndex == 0) {
holder.overflow.setViews(blocks, subredditName);
} else {
holder.overflow.setViews(blocks.subList(startIndex, blocks.size()), subredditName);
}
} else {
holder.overflow.removeAllViews();
}
}
@Override
public int getItemCount() {
if (dataSet.posts == null || dataSet.posts.isEmpty()) {
return 0;
} else {
return dataSet.posts.size() + 1;
}
}
public static void showModBottomSheet(final Context mContext,
final Comment comment, final ProfileCommentViewHolder holder,
final Map<String, Integer> reports, final Map<String, String> reports2) {
int[] attrs = new int[]{R.attr.tint};
TypedArray ta = mContext.obtainStyledAttributes(attrs);
//Initialize drawables
int color = ta.getColor(0, Color.WHITE);
Drawable profile = mContext.getResources().getDrawable(R.drawable.profile);
final Drawable report = mContext.getResources().getDrawable(R.drawable.report);
final Drawable approve = mContext.getResources().getDrawable(R.drawable.support);
final Drawable nsfw = mContext.getResources().getDrawable(R.drawable.hide);
final Drawable pin = mContext.getResources().getDrawable(R.drawable.sub);
final Drawable distinguish = mContext.getResources().getDrawable(R.drawable.iconstarfilled);
final Drawable remove = mContext.getResources().getDrawable(R.drawable.close);
final Drawable ban = mContext.getResources().getDrawable(R.drawable.ban);
final Drawable spam = mContext.getResources().getDrawable(R.drawable.spam);
//Tint drawables
profile.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
report.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
approve.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
nsfw.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
distinguish.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
remove.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
pin.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
ban.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
spam.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
ta.recycle();
//Bottom sheet builder
BottomSheet.Builder b = new BottomSheet.Builder((Activity) mContext).title(
Html.fromHtml(comment.getBody()));
int reportCount = reports.size() + reports2.size();
if (reportCount == 0) {
b.sheet(0, report, mContext.getString(R.string.mod_no_reports));
} else {
b.sheet(0, report, mContext.getResources()
.getQuantityString(R.plurals.mod_btn_reports, reportCount, reportCount));
}
b.sheet(1, approve, mContext.getString(R.string.mod_btn_approve));
// b.sheet(2, spam, mContext.getString(R.string.mod_btn_spam)) todo this
final boolean distinguished = !comment.getDataNode().get("distinguished").isNull();
if (comment.getAuthor().equalsIgnoreCase(Authentication.name)) {
if (!distinguished) {
b.sheet(9, distinguish, mContext.getString(R.string.mod_distinguish));
} else {
b.sheet(9, distinguish, mContext.getString(R.string.mod_undistinguish));
}
}
b.sheet(23, ban, mContext.getString(R.string.mod_ban_user));
b.sheet(6, remove, mContext.getString(R.string.btn_remove))
.sheet(10, spam, "Mark as spam")
.sheet(8, profile, mContext.getString(R.string.mod_btn_author))
.listener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0:
CommentAdapterHelper.viewReports(mContext, reports, reports2);
break;
case 1:
doApproval(mContext, holder, comment);
break;
case 9:
if (distinguished) {
unDistinguishComment(mContext, holder, comment);
} else {
distinguishComment(mContext, holder, comment);
}
break;
case 6:
removeComment(mContext, holder, comment, false);
break;
case 10:
removeComment(mContext, holder, comment, true);
break;
case 8:
Intent i = new Intent(mContext, Profile.class);
i.putExtra(Profile.EXTRA_PROFILE, comment.getAuthor());
mContext.startActivity(i);
break;
case 23:
CommentAdapterHelper.showBan(mContext, holder.itemView, comment, "", "", "", "");
break;
}
}
});
b.show();
}
public static void doApproval(final Context mContext, final ProfileCommentViewHolder holder,
final Comment comment) {
new AsyncTask<Void, Void, Boolean>() {
@Override
public void onPostExecute(Boolean b) {
if (b) {
Snackbar.make(holder.itemView, R.string.mod_approved, Snackbar.LENGTH_LONG)
.show();
} else {
new AlertDialogWrapper.Builder(mContext).setTitle(R.string.err_general)
.setMessage(R.string.err_retry_later)
.show();
}
}
@Override
protected Boolean doInBackground(Void... params) {
try {
new ModerationManager(Authentication.reddit).approve(comment);
} catch (ApiException e) {
e.printStackTrace();
return false;
}
return true;
}
}.execute();
}
public static void distinguishComment(final Context mContext, final ProfileCommentViewHolder holder,
final Comment comment) {
new AsyncTask<Void, Void, Boolean>() {
@Override
public void onPostExecute(Boolean b) {
if (b) {
Snackbar s = Snackbar.make(holder.itemView, R.string.comment_distinguished,
Snackbar.LENGTH_LONG);
View view = s.getView();
TextView tv =
(TextView) view.findViewById(android.support.design.R.id.snackbar_text);
tv.setTextColor(Color.WHITE);
s.show();
} else {
new AlertDialogWrapper.Builder(mContext).setTitle(R.string.err_general)
.setMessage(R.string.err_retry_later)
.show();
}
}
@Override
protected Boolean doInBackground(Void... params) {
try {
new ModerationManager(Authentication.reddit).setDistinguishedStatus(comment,
DistinguishedStatus.MODERATOR);
} catch (ApiException e) {
e.printStackTrace();
return false;
}
return true;
}
}.execute();
}
public static void unDistinguishComment(final Context mContext, final ProfileCommentViewHolder holder,
final Comment comment) {
new AsyncTask<Void, Void, Boolean>() {
@Override
public void onPostExecute(Boolean b) {
if (b) {
Snackbar s = Snackbar.make(holder.itemView, R.string.comment_undistinguished,
Snackbar.LENGTH_LONG);
View view = s.getView();
TextView tv =
(TextView) view.findViewById(android.support.design.R.id.snackbar_text);
tv.setTextColor(Color.WHITE);
s.show();
} else {
new AlertDialogWrapper.Builder(mContext).setTitle(R.string.err_general)
.setMessage(R.string.err_retry_later)
.show();
}
}
@Override
protected Boolean doInBackground(Void... params) {
try {
new ModerationManager(Authentication.reddit).setDistinguishedStatus(comment,
DistinguishedStatus.NORMAL);
} catch (ApiException e) {
e.printStackTrace();
return false;
}
return true;
}
}.execute();
}
public static void removeComment(final Context mContext, final ProfileCommentViewHolder holder,
final Comment comment, final boolean spam) {
new AsyncTask<Void, Void, Boolean>() {
@Override
public void onPostExecute(Boolean b) {
if (b) {
Snackbar s = Snackbar.make(holder.itemView, R.string.comment_removed,
Snackbar.LENGTH_LONG);
View view = s.getView();
TextView tv =
(TextView) view.findViewById(android.support.design.R.id.snackbar_text);
tv.setTextColor(Color.WHITE);
s.show();
} else {
new AlertDialogWrapper.Builder(mContext).setTitle(R.string.err_general)
.setMessage(R.string.err_retry_later)
.show();
}
}
@Override
protected Boolean doInBackground(Void... params) {
try {
new ModerationManager(Authentication.reddit).remove(comment, spam);
} catch (ApiException e) {
e.printStackTrace();
return false;
}
return true;
}
}.execute();
}
}