/* Copyright (C) 2014 Prasanna Thirumalai This file is part of StackX. StackX is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. StackX is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with StackX. If not, see <http://www.gnu.org/licenses/>. */ package com.prasanna.android.stacknetwork.fragment; import java.util.ArrayList; import android.app.FragmentTransaction; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.os.Bundle; import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.prasanna.android.http.HttpException; import com.prasanna.android.stacknetwork.R; import com.prasanna.android.stacknetwork.adapter.ItemListAdapter; import com.prasanna.android.stacknetwork.adapter.ItemListAdapter.ListItemView; import com.prasanna.android.stacknetwork.model.Comment; import com.prasanna.android.stacknetwork.receiver.RestQueryResultReceiver; import com.prasanna.android.stacknetwork.service.WriteIntentService; import com.prasanna.android.stacknetwork.utils.AppUtils; import com.prasanna.android.stacknetwork.utils.DateTimeUtils; import com.prasanna.android.stacknetwork.utils.DialogBuilder; import com.prasanna.android.stacknetwork.utils.OperatingSite; import com.prasanna.android.stacknetwork.utils.StringConstants; import com.prasanna.android.utils.LogWrapper; public class CommentFragment extends ItemListFragment<Comment> implements ListItemView<Comment> { private static final String TAG = CommentFragment.class.getSimpleName(); private ArrayList<Comment> comments; private ProgressDialog progressDialog; private OnCommentChangeListener onCommentChangeListener; private RestQueryResultReceiver addCommentResultReceiver; private LinearLayout postCommentFragmentContainer; private PostCommentFragment postCommentFragment; private CommentViewHolder selectedViewForReply; public interface OnShowCommentsListener { void onShowComments(); } public interface OnCommentChangeListener { void onCommentAdd(Comment comment); void onCommentUpdate(Comment comment); void onCommentDelete(long commentId); } static class CommentViewHolder { long id; RelativeLayout viewGroup; TextView score; TextView title; TextView owner; ImageView editComment; ImageView replyToComment; ImageView deleteComment; LinearLayout commentEditOptions; RelativeLayout commentWriteOptions; } public void setOnCommentChangeListener(OnCommentChangeListener onCommentChangeListener) { this.onCommentChangeListener = onCommentChangeListener; } public void setComments(ArrayList<Comment> comments) { this.comments = comments; } public void setResultReceiver(RestQueryResultReceiver resultReceiver) { this.addCommentResultReceiver = resultReceiver; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (itemsContainer == null) { if (comments == null) comments = new ArrayList<Comment>(); itemsContainer = (ViewGroup) inflater.inflate(R.layout.comment_list_view, container, false); postCommentFragmentContainer = (LinearLayout) itemsContainer.findViewById(R.id.post_comment_fragment_container); itemListAdapter = new ItemListAdapter<Comment>(getActivity(), R.layout.comment, comments, this); } return itemsContainer; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); getListView().setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); getListView().setItemsCanFocus(true); getListView().setClickable(false); } @Override protected String getReceiverExtraName() { return StringConstants.COMMENTS; } @Override protected void startIntentService() { } @Override protected String getLogTag() { return TAG; } @Override public View getView(final Comment comment, int position, View convertView, ViewGroup parent) { RelativeLayout commentLayout = (RelativeLayout) convertView; CommentViewHolder holder; if (commentLayout == null) { commentLayout = (RelativeLayout) getActivity().getLayoutInflater().inflate(R.layout.comment, null); holder = new CommentViewHolder(); holder.viewGroup = commentLayout; holder.score = (TextView) commentLayout.findViewById(R.id.commentScore); holder.title = (TextView) commentLayout.findViewById(R.id.commentTitle); holder.owner = (TextView) commentLayout.findViewById(R.id.commentOwner); holder.editComment = (ImageView) commentLayout.findViewById(R.id.editComment); holder.replyToComment = (ImageView) commentLayout.findViewById(R.id.replyToComment); holder.deleteComment = (ImageView) commentLayout.findViewById(R.id.deleteComment); holder.commentWriteOptions = (RelativeLayout) commentLayout.findViewById(R.id.commentWriteOptions); holder.commentEditOptions = (LinearLayout) commentLayout.findViewById(R.id.commentEditOptions); commentLayout.setTag(holder); } else holder = (CommentViewHolder) commentLayout.getTag(); holder.id = comment.id; holder.score.setText(AppUtils.formatNumber(comment.score)); holder.title.setText(""); holder.title.append(Html.fromHtml(comment.body)); holder.owner.setText(DateTimeUtils.getElapsedDurationSince(comment.creationDate) + " by " + Html.fromHtml(comment.owner.getDisplayName())); if (AppUtils.inAuthenticatedRealm(getActivity())) setupCommentWriteOptions(comment, position, holder); if (selectedViewForReply != null && selectedViewForReply.id == comment.id) { selectedViewForReply.viewGroup.setBackgroundColor(getResources().getColor(R.color.lightGrey)); selectedViewForReply.replyToComment.setVisibility(View.GONE); } else { holder.viewGroup.setBackgroundResource(R.drawable.rounded_border_grey_min_padding); if (!isMyComment(comment)) holder.replyToComment.setVisibility(View.VISIBLE); } return commentLayout; } private void setupCommentWriteOptions(final Comment comment, final int position, final CommentViewHolder holder) { boolean myComment = isMyComment(comment); holder.commentWriteOptions.setVisibility(View.VISIBLE); if (myComment) setupMyCommentOptions(comment, position, holder); else setupReplyToComment(comment, position, holder); } private boolean isMyComment(Comment comment) { long userId = OperatingSite.getSite().userId; if (userId > 0) return (comment.owner != null && comment.owner.id == userId); return false; } private void setupReplyToComment(final Comment comment, final int position, final CommentViewHolder holder) { holder.replyToComment.setVisibility(View.VISIBLE); holder.replyToComment.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismissAnotherReplyCommentEditTextIfExist(); selectedViewForReply = holder; selectedViewForReply.replyToComment.setVisibility(View.GONE); selectedViewForReply.viewGroup.setBackgroundColor(getResources().getColor(R.color.lightGrey)); LogWrapper.d(TAG, "Select comment for reply: " + selectedViewForReply.id); String draftText = comment.owner.isRegistered() ? "@" + comment.owner.getDisplayName().replaceAll("\\s", "") + " " : ""; displayPostCommentFragment(comment.post_id, comment.id, draftText, false, addCommentResultReceiver); getListView().smoothScrollToPositionFromTop(position, 0); } }); } private void setupMyCommentOptions(Comment comment, int position, CommentViewHolder holder) { holder.commentEditOptions.setVisibility(View.VISIBLE); setupEditComment(comment, position, holder); setupDeleteComment(comment.id, holder); } private void setupEditComment(final Comment comment, final int position, final CommentViewHolder holder) { holder.editComment.setVisibility(View.VISIBLE); holder.editComment.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { displayPostCommentFragment(comment.post_id, comment.id, comment.body, true, resultReceiver); getListView().smoothScrollToPositionFromTop(position, 0); AppUtils.showSoftInput(getActivity(), holder.title); } }); } private void setupDeleteComment(final long commentId, CommentViewHolder holder) { holder.deleteComment.setVisibility(View.VISIBLE); holder.deleteComment.setOnClickListener(new View.OnClickListener() { private OnClickListener listener = new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (which == DialogInterface.BUTTON_POSITIVE) startServiceForDelComment(commentId); } }; @Override public void onClick(View v) { DialogBuilder.yesNoDialog(getActivity(), R.string.sureQuestion, listener).show(); } }); } public boolean hasNoComments() { return comments == null || comments.isEmpty(); } private void removeSelf() { getFragmentManager().popBackStackImmediate(); } private void startServiceForDelComment(long commentId) { progressDialog = new ProgressDialog(getActivity(), R.style.dialogNoText); progressDialog.show(); Intent intent = new Intent(getActivity().getApplicationContext(), WriteIntentService.class); intent.putExtra(StringConstants.RESULT_RECEIVER, resultReceiver); intent.putExtra(StringConstants.COMMENT_ID, commentId); intent.putExtra(StringConstants.ACTION, WriteIntentService.ACTION_DEL_COMMENT); startService(intent); } @Override public void onReceiveResult(int resultCode, Bundle resultData) { serviceRunning = false; if (progressDialog != null && progressDialog.isShowing()) progressDialog.dismiss(); switch (resultCode) { case WriteIntentService.ACTION_ADD_COMMENT: LogWrapper.d(TAG, "Receiver invoked for ACTION_ADD_COMMENT"); onAddCommentComplete(resultData); break; case WriteIntentService.ACTION_EDIT_COMMENT: LogWrapper.d(TAG, "Receiver invoked for ACTION_EDIT_COMMENT"); onEditCommentComplete(resultData); dismissPostCommentFragment(); break; case WriteIntentService.ACTION_DEL_COMMENT: LogWrapper.d(TAG, "Receiver invoked for ACTION_DEL_COMMENT"); onDelCommentComplete(resultData); break; case WriteIntentService.ERROR: displayError(resultData); break; } } private void displayError(Bundle resultData) { int requestCode = resultData.getInt(StringConstants.REQUEST_CODE, -1); if (requestCode == WriteIntentService.ACTION_ADD_COMMENT) { HttpException e = (HttpException) resultData.getSerializable(StringConstants.EXCEPTION); String errorMsg = "Request failed for unknown reason"; if (e != null) postCommentFragment.setSendError(e.getErrorResponse()); else postCommentFragment.setSendError(errorMsg); } } private void onAddCommentComplete(Bundle resultData) { Comment comment = (Comment) resultData.getSerializable(StringConstants.COMMENT); if (comment != null && onCommentChangeListener != null) { comments.add(comment); onCommentChangeListener.onCommentAdd(comment); itemListAdapter.notifyDataSetChanged(); } } private void onEditCommentComplete(Bundle resultData) { Comment comment = (Comment) resultData.getSerializable(StringConstants.COMMENT); if (comment != null && onCommentChangeListener != null) { onCommentChangeListener.onCommentUpdate(comment); int idx = comments.indexOf(comment); if (idx != -1) { comments.remove(idx); comments.add(idx, comment); } itemListAdapter.notifyDataSetChanged(); } } private void onDelCommentComplete(Bundle resultData) { if (onCommentChangeListener != null) { onCommentChangeListener.onCommentDelete(resultData.getLong(StringConstants.COMMENT_ID)); itemListAdapter.notifyDataSetChanged(); if (comments.isEmpty()) removeSelf(); } } public boolean onBackPressed() { dismissAnotherReplyCommentEditTextIfExist(); postCommentFragmentContainer.setVisibility(View.GONE); selectedViewForReply = null; return true; } private void dismissAnotherReplyCommentEditTextIfExist() { if (selectedViewForReply != null) { selectedViewForReply.viewGroup.setBackgroundResource(R.drawable.rounded_border_grey_min_padding); selectedViewForReply.replyToComment.setVisibility(View.VISIBLE); } } private void displayPostCommentFragment(long postId, long commenId, String draftText, boolean myEdit, RestQueryResultReceiver receiver) { postCommentFragment = (PostCommentFragment) getFragmentManager().findFragmentByTag("postCommentFragment"); if (postCommentFragment == null) addPostCommentFragment(); postCommentFragment.setPostId(postId); postCommentFragment.setCommentId(commenId); postCommentFragment.setDraftText(draftText); postCommentFragment.setResultReceiver(receiver); postCommentFragment.setMyEdit(myEdit); if (myEdit) postCommentFragment.setTitle("Editing"); else postCommentFragment.setTitle("Replying to comment"); if (postCommentFragment.isVisible()) postCommentFragment.refreshView(); postCommentFragmentContainer.setVisibility(View.VISIBLE); } private void addPostCommentFragment() { postCommentFragment = new PostCommentFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.post_comment_fragment_container, postCommentFragment, "postCommentFragment"); transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); transaction.addToBackStack(null); transaction.commit(); } private void dismissPostCommentFragment() { if (postCommentFragment != null) { postCommentFragment.hideSoftKeyboard(); getFragmentManager().popBackStackImmediate(); postCommentFragment = null; } } @Override protected void loadNextPage() { } }