Java tutorial
package com.wellsandwhistles.android.redditsp.reddit.api; /** This file was either copied or modified from https://github.com/QuantumBadger/RedReader * under the Free Software Foundation General Public License version 3*/ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.text.ClipboardManager; import android.widget.Toast; import org.apache.commons.lang3.StringEscapeUtils; import com.wellsandwhistles.android.redditsp.R; import com.wellsandwhistles.android.redditsp.account.RedditAccount; import com.wellsandwhistles.android.redditsp.account.RedditAccountManager; import com.wellsandwhistles.android.redditsp.activities.CommentEditActivity; import com.wellsandwhistles.android.redditsp.activities.CommentReplyActivity; import com.wellsandwhistles.android.redditsp.cache.CacheManager; import com.wellsandwhistles.android.redditsp.cache.CacheRequest; import com.wellsandwhistles.android.redditsp.common.General; import com.wellsandwhistles.android.redditsp.common.LinkHandler; import com.wellsandwhistles.android.redditsp.common.SRError; import com.wellsandwhistles.android.redditsp.common.SRTime; import com.wellsandwhistles.android.redditsp.fragments.CommentListingFragment; import com.wellsandwhistles.android.redditsp.fragments.CommentPropertiesDialog; import com.wellsandwhistles.android.redditsp.reddit.APIResponseHandler; import com.wellsandwhistles.android.redditsp.reddit.RedditAPI; import com.wellsandwhistles.android.redditsp.reddit.prepared.RedditChangeDataManager; import com.wellsandwhistles.android.redditsp.reddit.prepared.RedditRenderableComment; import com.wellsandwhistles.android.redditsp.reddit.things.RedditComment; import com.wellsandwhistles.android.redditsp.reddit.url.UserProfileURL; import com.wellsandwhistles.android.redditsp.views.RedditCommentView; import java.util.ArrayList; import java.util.HashSet; public class RedditAPICommentAction { public enum RedditCommentAction { UPVOTE, UNVOTE, DOWNVOTE, SAVE, UNSAVE, REPORT, SHARE, COPY_TEXT, COPY_URL, REPLY, USER_PROFILE, COMMENT_LINKS, COLLAPSE, EDIT, DELETE, PROPERTIES, CONTEXT, GO_TO_COMMENT, ACTION_MENU, BACK } private static class RCVMenuItem { public final String title; public final RedditCommentAction action; private RCVMenuItem(Context context, int titleRes, RedditCommentAction action) { this.title = context.getString(titleRes); this.action = action; } } public static void showActionMenu(final AppCompatActivity activity, final CommentListingFragment commentListingFragment, final RedditRenderableComment comment, final RedditCommentView commentView, final RedditChangeDataManager changeDataManager, final boolean isArchived) { final RedditAccount user = RedditAccountManager.getInstance(activity).getDefaultAccount(); final ArrayList<RCVMenuItem> menu = new ArrayList<>(); if (!user.isAnonymous()) { if (!isArchived) { if (!changeDataManager.isUpvoted(comment)) { menu.add(new RCVMenuItem(activity, R.string.action_upvote, RedditCommentAction.UPVOTE)); } else { menu.add(new RCVMenuItem(activity, R.string.action_upvote_remove, RedditCommentAction.UNVOTE)); } if (!changeDataManager.isDownvoted(comment)) { menu.add(new RCVMenuItem(activity, R.string.action_downvote, RedditCommentAction.DOWNVOTE)); } else { menu.add( new RCVMenuItem(activity, R.string.action_downvote_remove, RedditCommentAction.UNVOTE)); } } if (changeDataManager.isSaved(comment)) { menu.add(new RCVMenuItem(activity, R.string.action_unsave, RedditCommentAction.UNSAVE)); } else { menu.add(new RCVMenuItem(activity, R.string.action_save, RedditCommentAction.SAVE)); } menu.add(new RCVMenuItem(activity, R.string.action_report, RedditCommentAction.REPORT)); if (!isArchived) menu.add(new RCVMenuItem(activity, R.string.action_reply, RedditCommentAction.REPLY)); if (user.username.equalsIgnoreCase(comment.getParsedComment().getRawComment().author)) { if (!isArchived) menu.add(new RCVMenuItem(activity, R.string.action_edit, RedditCommentAction.EDIT)); menu.add(new RCVMenuItem(activity, R.string.action_delete, RedditCommentAction.DELETE)); } } menu.add(new RCVMenuItem(activity, R.string.action_comment_context, RedditCommentAction.CONTEXT)); menu.add(new RCVMenuItem(activity, R.string.action_comment_go_to, RedditCommentAction.GO_TO_COMMENT)); menu.add(new RCVMenuItem(activity, R.string.action_comment_links, RedditCommentAction.COMMENT_LINKS)); if (commentListingFragment != null) { menu.add(new RCVMenuItem(activity, R.string.action_collapse, RedditCommentAction.COLLAPSE)); } menu.add(new RCVMenuItem(activity, R.string.action_share, RedditCommentAction.SHARE)); menu.add(new RCVMenuItem(activity, R.string.action_copy_text, RedditCommentAction.COPY_TEXT)); menu.add(new RCVMenuItem(activity, R.string.action_copy_link, RedditCommentAction.COPY_URL)); menu.add(new RCVMenuItem(activity, R.string.action_user_profile, RedditCommentAction.USER_PROFILE)); menu.add(new RCVMenuItem(activity, R.string.action_properties, RedditCommentAction.PROPERTIES)); final String[] menuText = new String[menu.size()]; for (int i = 0; i < menuText.length; i++) { menuText[i] = menu.get(i).title; } final AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setItems(menuText, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { onActionMenuItemSelected(comment, commentView, activity, commentListingFragment, menu.get(which).action, changeDataManager); } }); final AlertDialog alert = builder.create(); alert.setCanceledOnTouchOutside(true); alert.show(); } public static void onActionMenuItemSelected(final RedditRenderableComment renderableComment, final RedditCommentView commentView, final AppCompatActivity activity, final CommentListingFragment commentListingFragment, final RedditCommentAction action, final RedditChangeDataManager changeDataManager) { final RedditComment comment = renderableComment.getParsedComment().getRawComment(); switch (action) { case UPVOTE: action(activity, comment, RedditAPI.ACTION_UPVOTE, changeDataManager); break; case DOWNVOTE: action(activity, comment, RedditAPI.ACTION_DOWNVOTE, changeDataManager); break; case UNVOTE: action(activity, comment, RedditAPI.ACTION_UNVOTE, changeDataManager); break; case SAVE: action(activity, comment, RedditAPI.ACTION_SAVE, changeDataManager); break; case UNSAVE: action(activity, comment, RedditAPI.ACTION_UNSAVE, changeDataManager); break; case REPORT: new AlertDialog.Builder(activity).setTitle(R.string.action_report) .setMessage(R.string.action_report_sure) .setPositiveButton(R.string.action_report, new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { action(activity, comment, RedditAPI.ACTION_REPORT, changeDataManager); } }).setNegativeButton(R.string.dialog_cancel, null).show(); break; case REPLY: { final Intent intent = new Intent(activity, CommentReplyActivity.class); intent.putExtra(CommentReplyActivity.PARENT_ID_AND_TYPE_KEY, comment.getIdAndType()); intent.putExtra(CommentReplyActivity.PARENT_MARKDOWN_KEY, StringEscapeUtils.unescapeHtml4(comment.body)); activity.startActivity(intent); break; } case EDIT: { final Intent intent = new Intent(activity, CommentEditActivity.class); intent.putExtra("commentIdAndType", comment.getIdAndType()); intent.putExtra("commentText", StringEscapeUtils.unescapeHtml4(comment.body)); activity.startActivity(intent); break; } case DELETE: { new AlertDialog.Builder(activity).setTitle(R.string.accounts_delete).setMessage(R.string.delete_confirm) .setPositiveButton(R.string.action_delete, new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { action(activity, comment, RedditAPI.ACTION_DELETE, changeDataManager); } }).setNegativeButton(R.string.dialog_cancel, null).show(); break; } case COMMENT_LINKS: final HashSet<String> linksInComment = comment.computeAllLinks(); if (linksInComment.isEmpty()) { General.quickToast(activity, R.string.error_toast_no_urls_in_comment); } else { final String[] linksArr = linksInComment.toArray(new String[linksInComment.size()]); final AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setItems(linksArr, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { LinkHandler.onLinkClicked(activity, linksArr[which], false); dialog.dismiss(); } }); final AlertDialog alert = builder.create(); alert.setTitle(R.string.action_comment_links); alert.setCanceledOnTouchOutside(true); alert.show(); } break; case SHARE: final Intent mailer = new Intent(Intent.ACTION_SEND); mailer.setType("text/plain"); mailer.putExtra(Intent.EXTRA_SUBJECT, "Comment by " + comment.author + " on Reddit"); // TODO this currently just dumps the markdown mailer.putExtra(Intent.EXTRA_TEXT, StringEscapeUtils.unescapeHtml4(comment.body) + "\r\n\r\n" + comment.getContextUrl().generateNonJsonUri().toString()); activity.startActivityForResult(Intent.createChooser(mailer, activity.getString(R.string.action_share)), 1); break; case COPY_TEXT: { ClipboardManager manager = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE); // TODO this currently just dumps the markdown manager.setText(StringEscapeUtils.unescapeHtml4(comment.body)); break; } case COPY_URL: { ClipboardManager manager = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE); // TODO this currently just dumps the markdown manager.setText(comment.getContextUrl().context(null).generateNonJsonUri().toString()); break; } case COLLAPSE: { commentListingFragment.handleCommentVisibilityToggle(commentView); break; } case USER_PROFILE: LinkHandler.onLinkClicked(activity, new UserProfileURL(comment.author).toString()); break; case PROPERTIES: CommentPropertiesDialog.newInstance(comment).show(activity.getSupportFragmentManager(), null); break; case GO_TO_COMMENT: { LinkHandler.onLinkClicked(activity, comment.getContextUrl().context(null).toString()); break; } case CONTEXT: { LinkHandler.onLinkClicked(activity, comment.getContextUrl().toString()); break; } case ACTION_MENU: showActionMenu(activity, commentListingFragment, renderableComment, commentView, changeDataManager, comment.isArchived()); break; case BACK: activity.onBackPressed(); break; } } public static void action(final AppCompatActivity activity, final RedditComment comment, final @RedditAPI.RedditAction int action, final RedditChangeDataManager changeDataManager) { final RedditAccount user = RedditAccountManager.getInstance(activity).getDefaultAccount(); if (user.isAnonymous()) { General.quickToast(activity, activity.getString(R.string.error_toast_notloggedin)); return; } final boolean wasUpvoted = changeDataManager.isUpvoted(comment); final boolean wasDownvoted = changeDataManager.isUpvoted(comment); switch (action) { case RedditAPI.ACTION_DOWNVOTE: if (!comment.isArchived()) { changeDataManager.markDownvoted(SRTime.utcCurrentTimeMillis(), comment); } break; case RedditAPI.ACTION_UNVOTE: if (!comment.isArchived()) { changeDataManager.markUnvoted(SRTime.utcCurrentTimeMillis(), comment); } break; case RedditAPI.ACTION_UPVOTE: if (!comment.isArchived()) { changeDataManager.markUpvoted(SRTime.utcCurrentTimeMillis(), comment); } break; case RedditAPI.ACTION_SAVE: changeDataManager.markSaved(SRTime.utcCurrentTimeMillis(), comment, true); break; case RedditAPI.ACTION_UNSAVE: changeDataManager.markSaved(SRTime.utcCurrentTimeMillis(), comment, false); break; } boolean vote = (action == RedditAPI.ACTION_DOWNVOTE | action == RedditAPI.ACTION_UPVOTE | action == RedditAPI.ACTION_UNVOTE); if (comment.isArchived() && vote) { Toast.makeText(activity, R.string.error_archived_vote, Toast.LENGTH_SHORT).show(); return; } RedditAPI.action(CacheManager.getInstance(activity), new APIResponseHandler.ActionResponseHandler(activity) { @Override protected void onCallbackException(final Throwable t) { throw new RuntimeException(t); } @Override protected void onFailure(final @CacheRequest.RequestFailureType int type, final Throwable t, final Integer status, final String readableMessage) { revertOnFailure(); if (t != null) t.printStackTrace(); final SRError error = General.getGeneralErrorForFailure(context, type, t, status, null); General.UI_THREAD_HANDLER.post(new Runnable() { @Override public void run() { General.showResultDialog(activity, error); } }); } @Override protected void onFailure(final APIFailureType type) { revertOnFailure(); final SRError error = General.getGeneralErrorForFailure(context, type); General.UI_THREAD_HANDLER.post(new Runnable() { @Override public void run() { General.showResultDialog(activity, error); } }); } @Override protected void onSuccess() { if (action == RedditAPI.ACTION_DELETE) { General.quickToast(context, R.string.delete_success); } } private void revertOnFailure() { switch (action) { case RedditAPI.ACTION_DOWNVOTE: case RedditAPI.ACTION_UNVOTE: case RedditAPI.ACTION_UPVOTE: if (wasUpvoted) { changeDataManager.markUpvoted(SRTime.utcCurrentTimeMillis(), comment); } else if (wasDownvoted) { changeDataManager.markDownvoted(SRTime.utcCurrentTimeMillis(), comment); } else { changeDataManager.markUnvoted(SRTime.utcCurrentTimeMillis(), comment); } case RedditAPI.ACTION_SAVE: changeDataManager.markSaved(SRTime.utcCurrentTimeMillis(), comment, false); break; case RedditAPI.ACTION_UNSAVE: changeDataManager.markSaved(SRTime.utcCurrentTimeMillis(), comment, true); break; } } }, user, comment.getIdAndType(), action, activity); } }