package com.dozuki.ifixit.ui.guide; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.Toast; import android.widget.ViewSwitcher; import com.actionbarsherlock.view.MenuItem; import com.dozuki.ifixit.App; import com.dozuki.ifixit.R; import com.dozuki.ifixit.model.Comment; import com.dozuki.ifixit.model.guide.Guide; import com.dozuki.ifixit.model.user.LoginEvent; import com.dozuki.ifixit.ui.BaseActivity; import com.dozuki.ifixit.ui.guide.view.GuideViewActivity; import com.dozuki.ifixit.util.api.Api; import com.dozuki.ifixit.util.api.ApiCall; import com.dozuki.ifixit.util.api.ApiEvent; import com.squareup.otto.Subscribe; import java.util.ArrayList; import java.util.Iterator; public class CommentsActivity extends BaseActivity { private static final String COMMENTS_KEY = "COMMENTS_KEY"; private static final String TITLE_KEY = "TITLE_FIELD"; private static final String CONTEXTID = "CONTEXTID_KEY"; private static final String CONTEXT = "CONTEXT_KEY"; private static final String GUIDEID_KEY = "GUIDEID_KEY"; private static final String PARENTID_KEY = "PARENTID_KEY"; private ArrayList<Comment> mComments = new ArrayList<Comment>(); private String mTitle; private CommentsAdapter mAdapter; private ListView mCommentsList; private EditText mAddCommentField; private String mCommentContext; private int mCommentContextId; private int mGuideid; private ImageButton mAddCommentButton; private ProgressBar mAddCommentProgress; private Integer mParentId; public static Intent viewComments(Context context, ArrayList<Comment> comments, String title, String commentContext, int contextid) { Intent intent = new Intent(context, CommentsActivity.class); intent.putExtra(TITLE_KEY, title); intent.putExtra(CONTEXTID, contextid); intent.putExtra(CONTEXT, commentContext); intent.putExtra(COMMENTS_KEY, comments); return intent; } public static Intent viewGuideComments(Context context, ArrayList<Comment> comments, String title, String commentContext, int contextid, int guideid) { Intent intent = viewComments(context, comments, title, commentContext, contextid); intent.putExtra(GUIDEID_KEY, guideid); return intent; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.comments); getSupportActionBar().setDisplayHomeAsUpEnabled(true); Bundle args = getIntent().getExtras(); if (savedInstanceState != null) { mComments = (ArrayList<Comment>) savedInstanceState.getSerializable(COMMENTS_KEY); mCommentContext = savedInstanceState.getString(CONTEXT); mCommentContextId = savedInstanceState.getInt(CONTEXTID); mTitle = savedInstanceState.getString(TITLE_KEY); mGuideid = savedInstanceState.getInt(GUIDEID_KEY, 0); mParentId = (Integer)savedInstanceState.getSerializable(PARENTID_KEY); } else if (args != null) { mComments = (ArrayList<Comment>) args.getSerializable(COMMENTS_KEY); mCommentContext = args.getString(CONTEXT); mCommentContextId = args.getInt(CONTEXTID); mTitle = args.getString(TITLE_KEY); mGuideid = args.getInt(GUIDEID_KEY, 0); } else { mTitle = getString(R.string.comments); } mAddCommentField = (EditText) findViewById(R.id.add_comment_field); mAddCommentProgress = (ProgressBar) findViewById(R.id.add_comment_progress); mAddCommentButton = (ImageButton) findViewById(R.id.add_comment_button); mAddCommentButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String commentText = String.valueOf(mAddCommentField.getText()); Object parentid = mAddCommentField.getTag(R.id.comment_parent_id); if (commentText.length() > 0) { mAddCommentField.setEnabled(false); mAddCommentButton.setVisibility(View.GONE); mAddCommentProgress.setVisibility(View.VISIBLE); if (parentid != null) { App.sendEvent("ui_action", "button_press", "comment_add_reply", null); Api.call(CommentsActivity.this, ApiCall.newComment(commentText, mCommentContext, mCommentContextId, (Integer) parentid)); } else { App.sendEvent("ui_action", "button_press", "comment_add_new", null); Api.call(CommentsActivity.this, ApiCall.newComment(commentText, mCommentContext, mCommentContextId)); } } } }); mCommentsList = (ListView) findViewById(R.id.comment_list); mCommentsList.setEmptyView(findViewById(android.R.id.empty)); mAdapter = new CommentsAdapter(this, mComments); mCommentsList.setAdapter(mAdapter); setTitle(mTitle); if (App.get().isUserLoggedIn()) { if (mCommentContext.equalsIgnoreCase("guide") || mCommentContext.equalsIgnoreCase("step")) { Api.call(this, ApiCall.guide(mGuideid)); } else { // TODO: Get wiki comments once we add those endpoints. } } if (mParentId != null) { App.getBus().post(new CommentReplyingEvent(mParentId)); } } @Override public void onSaveInstanceState(Bundle state) { super.onSaveInstanceState(state); state.putSerializable(COMMENTS_KEY, mComments); state.putInt(CONTEXTID, mCommentContextId); state.putString(CONTEXT, mCommentContext); state.putString(TITLE_KEY, mTitle); state.putInt(GUIDEID_KEY, mGuideid); state.putSerializable(PARENTID_KEY, mParentId); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { // Respond to the action bar's Up/Home button case android.R.id.home: finishCommentsActivity(); return true; default: return super.onOptionsItemSelected(item); } } @Override public void onBackPressed() { finishCommentsActivity(); } private void finishCommentsActivity() { Intent data = new Intent(); data.putExtra(GuideViewActivity.COMMENTS_TAG, mComments); if (getParent() == null) { setResult(Activity.RESULT_OK, data); } else { getParent().setResult(Activity.RESULT_OK, data); } finish(); } @Subscribe public void onGuideGet(ApiEvent.ViewGuide event) { if (!event.hasError()) { Guide guide = event.getResult(); if (mCommentContext.equalsIgnoreCase("guide")) { mComments = guide.getComments(); } else if (mCommentContext.equalsIgnoreCase("step")) { mComments = guide.getStepById(mCommentContextId).getComments(); } mAdapter.setComments(mComments); mAdapter.notifyDataSetChanged(); } } @Subscribe public void onCommentDelete(CommentDeleteEvent event) { Api.call(this, ApiCall.deleteComment(event.comment.mCommentid)); } @Subscribe public void onCommentDeleted(ApiEvent.DeleteComment event) { if (!event.hasError()) { int commentIdToDelete = Integer.parseInt(event.getExtraInfo()); for (Iterator<Comment> it = mComments.iterator(); it.hasNext(); ) { Comment comment = it.next(); if (comment.mCommentid == commentIdToDelete) { it.remove(); break; } else { for (Iterator<Comment> rit = comment.mReplies.iterator(); rit.hasNext(); ) { Comment reply = rit.next(); if (reply.mCommentid == commentIdToDelete) { rit.remove(); break; } } } } mAdapter.setComments(mComments); mAdapter.notifyDataSetChanged(); } else { Toast.makeText(this, R.string.error_deleting_comment, Toast.LENGTH_SHORT).show(); } } @Subscribe public void onCommentEditing(final CommentEditEvent event) { final View viewRoot = findViewById(event.comment.mCommentid); final View editContainer = viewRoot.findViewById(R.id.edit_comment_container); final EditText editCommentField = (EditText) viewRoot.findViewById(R.id.edit_comment_text); final ViewSwitcher switcher = (ViewSwitcher) viewRoot.findViewById(R.id.edit_comment_switcher); switcher.showNext(); editContainer.setVisibility(View.VISIBLE); editCommentField.setText(event.comment.mTextRaw); viewRoot.findViewById(R.id.save_edit_comment_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String updatedText = editCommentField.getText().toString(); // Fire off the edit request only if the comment was changed if (!updatedText.equals(event.comment.mTextRaw)) { App.sendEvent("ui_action", "button_press", "comment_edited", null); viewRoot.findViewById(R.id.comment_progress).setVisibility(View.VISIBLE); viewRoot.findViewById(R.id.comment_menu).setVisibility(View.GONE); v.setEnabled(false); Api.call(CommentsActivity.this, ApiCall.editComment(updatedText, event.comment.mCommentid)); } } }); viewRoot.findViewById(R.id.exit_comment_edit_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { App.sendEvent("ui_action", "button_press", "comment_exit_edit", null); switcher.showPrevious(); editContainer.setVisibility(View.GONE); editCommentField.setText(""); } }); } @Subscribe public void onCommentEdited(ApiEvent.EditComment event) { if (!event.hasError()) { Comment comment = event.getResult(); for (Comment c : mComments) { if (comment.isReply() && c.mCommentid == comment.mParentid) { for (Comment reply : c.mReplies) { if (reply.mCommentid == comment.mCommentid) { reply.mTextRaw = comment.mTextRaw; reply.mTextRendered = comment.mTextRendered; break; } } break; } else if (comment.mCommentid == c.mCommentid) { c.mTextRaw = comment.mTextRaw; c.mTextRendered = comment.mTextRendered; } } mAdapter.setComments(mComments); } else { Toast.makeText(this, event.getError().mMessage, Toast.LENGTH_SHORT).show(); } mAdapter.notifyDataSetChanged(); } @Subscribe public void onCommentReplying(CommentReplyingEvent event) { mAddCommentField.setHint(R.string.add_reply); mAddCommentField.requestFocus(); showSoftKeyboard(); mAddCommentField.setTag(R.id.comment_parent_id, event.parentid); mParentId = event.parentid; Button exitReply = (Button) findViewById(R.id.exit_comment_reply_button); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 7f); mAddCommentField.setLayoutParams(params); exitReply.setVisibility(View.VISIBLE); exitReply.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { App.sendEvent("ui_action", "button_press", "comment_exit_reply", null); resetCommentField(false); v.setVisibility(View.GONE); } }); } @Subscribe public void onCommentAdd(ApiEvent.AddComment event) { if (!event.hasError()) { int position = 0; Comment comment = event.getResult(); if (comment.isReply()) { for (Comment c : mComments) { if (c.mCommentid == comment.mParentid) { c.mReplies.add(c.mReplies.size(), comment); break; } position++; } } else { mComments.add(mComments.size(), comment); position = mComments.size(); } mAdapter.setComments(mComments); mAdapter.notifyDataSetChanged(); scrollCommentsToPosition(position); resetCommentField(false); } else { Toast.makeText(this, event.getError().mMessage, Toast.LENGTH_SHORT).show(); } mAddCommentField.setEnabled(true); mAddCommentButton.setVisibility(View.VISIBLE); mAddCommentProgress.setVisibility(View.GONE); } @Subscribe public void onCancelLogin(LoginEvent.Cancel event) { resetCommentField(true); } private void resetCommentField(boolean keepText) { if (!keepText) { mAddCommentField.setText(""); mAddCommentField.setHint(R.string.add_comment); mAddCommentField.setTag(R.id.comment_parent_id, null); mParentId = null; findViewById(R.id.exit_comment_reply_button).setVisibility(View.GONE); } mAddCommentField.setEnabled(true); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 8f); mAddCommentField.setLayoutParams(params); mAddCommentButton.setVisibility(View.VISIBLE); mAddCommentProgress.setVisibility(View.GONE); } private void scrollCommentsToPosition(final int position) { new Handler().post(new Runnable() { @Override public void run() { mCommentsList.setSelection(position); } }); } private void showSoftKeyboard() { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInputFromWindow(mAddCommentField.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0); } }