package com.vishwa.pinit;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import com.parse.DeleteCallback;
import com.parse.FindCallback;
import com.parse.GetCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseRelation;
import com.parse.ParseUser;
import com.parse.SaveCallback;
public class CommentsActivity extends Activity {
public final static int DISPLAY_NOTE_LIKES = 107;
private Button mSendCommentButton;
private ImageButton mLikeButton;
private ImageButton mShowLikesButton;
private EditText mCommentField;
private TextView mNumberOfLikes;
private ListView mCommentsListView;
private ParseObject mParseNote = DisplayNoteActivity.mParseNote;
private int mNoteLikesCount;
private int mNoteCommentsCount;
private int mNumberOfCommentsLoaded = 0;
private int mNumberOfLikesLoaded = 0;
private boolean mUserLikesNote;
private boolean mShowingLikes;
private ArrayList<NoteComment> mNoteComments = new ArrayList<NoteComment>();
private ArrayList<NoteLike> mNoteLikes = new ArrayList<NoteLike>();
private CommentsArrayAdapter mAdapter;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_comments_display);
mSendCommentButton = (Button) findViewById(R.id.comments_send_comment);
mLikeButton = (ImageButton) findViewById(R.id.comments_like_button);
mShowLikesButton = (ImageButton) findViewById(R.id.comments_show_likes);
mCommentField = (EditText) findViewById(R.id.comments_new_comment);
mNumberOfLikes = (TextView) findViewById(R.id.comments_number_of_likes);
mCommentsListView = (ListView) findViewById(R.id.comments_listview);
mAdapter = new CommentsArrayAdapter(
this, 0, mNoteComments, ((PinItApplication)getApplication()).getImageLoader());
mCommentsListView.setAdapter(mAdapter);
mCommentsListView.setDivider(null);
mCommentsListView.setDividerHeight(0);
mCommentsListView.setOnScrollListener(new EndlessScrollListener());
Intent intent = getIntent();
mNoteLikesCount = intent.getIntExtra("noteLikesCount", 0);
mNoteCommentsCount = intent.getIntExtra("noteCommentsCount", 0);
mUserLikesNote = intent.getBooleanExtra("userLikesNote", false);
mNumberOfCommentsLoaded = intent.getIntExtra("numberOfCommentsLoaded", 0);
ArrayList<NoteComment> comments = intent.getParcelableArrayListExtra("noteComments");
for(NoteComment comment : comments) {
mNoteComments.add(comment);
}
mAdapter.notifyDataSetChanged();
setActivityResult();
if(mNoteCommentsCount > 0) {
mCommentsListView.setBackgroundDrawable(null);
}
if(mUserLikesNote) {
mLikeButton.setImageResource(R.drawable.heart_red);
}
else {
mLikeButton.setImageResource(R.drawable.heart);
}
updateLikesSize();
loadLikesInBackground();
loadMoreComments();
mNumberOfLikes.setOnClickListener(new OnShowLikesButtonClickListener());
mShowLikesButton.setOnClickListener(new OnShowLikesButtonClickListener());
mLikeButton.setOnClickListener(new OnLikeButtonClickListener());
mSendCommentButton.setOnClickListener(new OnCommentButtonClickListener());
}
public class OnLikeButtonClickListener implements OnClickListener {
@Override
public void onClick(View likeButtonView) {
if(mUserLikesNote) {
mUserLikesNote = false;
mLikeButton.setImageResource(R.drawable.heart);
mLikeButton.setEnabled(false);
mNoteLikesCount--;
updateLikesSize();
final ParseRelation relation = mParseNote.getRelation("likes");
ParseQuery query = new ParseQuery("Like");
query.whereEqualTo("creator", ParseUser.getCurrentUser());
query.whereEqualTo("noteId", mParseNote.getObjectId());
query.getFirstInBackground(new GetCallback() {
@Override
public void done(final ParseObject object, ParseException e) {
if(e == null) {
relation.remove(object);
mParseNote.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if(e == null) {
object.deleteInBackground(new DeleteCallback() {
@Override
public void done(ParseException e) {
if(e == null) {
Iterator<NoteLike> iterator = mNoteLikes.iterator();
while(iterator.hasNext()) {
NoteLike like = iterator.next();
if(like.getCommentCreator().equals(
ParseUser.getCurrentUser().getUsername())) {
iterator.remove();
break;
}
}
setActivityResult();
mLikeButton.setEnabled(true);
}
}
});
}
}
});
}
}
});
}
else {
mUserLikesNote = true;
mLikeButton.setImageResource(R.drawable.heart_red);
final Animation likeButtonAnimation =
AnimationUtils.loadAnimation(CommentsActivity.this, R.anim.like_button_anim);
likeButtonView.startAnimation(likeButtonAnimation);
mLikeButton.setEnabled(false);
mNoteLikesCount++;
updateLikesSize();
final ParseRelation relation = mParseNote.getRelation("likes");
final ParseObject like = new ParseObject("Like");
like.put("creator", ParseUser.getCurrentUser());
like.put("creatorName", ParseUser.getCurrentUser().getUsername());
like.put("noteId", mParseNote.getObjectId());
if(ParseUser.getCurrentUser().getBoolean("isDefaultPhoto")) {
like.put("creatorPhotoUrl", "http://s3.amazonaws.com/pinit/default_image.png");
}
else {
like.put("creatorPhotoUrl",
ParseUser.getCurrentUser()
.getParseFile("profilePhotoThumbnail")
.getUrl());
}
like.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if(e == null) {
relation.add(like);
mParseNote.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
NoteLike like;
if(ParseUser.getCurrentUser().getBoolean("isDefaultPhoto")) {
like = new NoteLike(
ParseUser.getCurrentUser().getUsername(),
"http://s3.amazonaws.com/pinit/default_image.png",
mParseNote.getObjectId());
}
else {
like = new NoteLike(
ParseUser.getCurrentUser().getUsername(),
ParseUser.getCurrentUser()
.getParseFile("profilePhotoThumbnail")
.getUrl(),
mParseNote.getObjectId());
}
mNoteLikes.add(like);
setActivityResult();
mLikeButton.setEnabled(true);
}
});
}
}
});
}
}
}
public class OnShowLikesButtonClickListener implements OnClickListener {
@Override
public void onClick(View v) {
if(!mNumberOfLikes.getText().toString().equals("Be the first to like this!")) {
mShowingLikes = true;
Intent intent = new Intent(getApplicationContext(), LikesActivity.class);
intent.putExtra("numberofLikesLoaded", mNumberOfLikesLoaded);
intent.putParcelableArrayListExtra("noteLikes", mNoteLikes);
startActivityForResult(intent, DISPLAY_NOTE_LIKES);
}
}
}
public class OnCommentButtonClickListener implements OnClickListener{
@Override
public void onClick(View v) {
if(!mCommentField.getText().toString().isEmpty()) {
mSendCommentButton.setEnabled(false);
final ParseRelation relation = mParseNote.getRelation("comments");
final ParseObject comment = new ParseObject("Comment");
comment.put("creator", ParseUser.getCurrentUser());
comment.put("noteId", mParseNote.getObjectId());
comment.put("commentText", mCommentField.getText().toString());
comment.put("creatorName", ParseUser.getCurrentUser().getUsername());
if(ParseUser.getCurrentUser().getBoolean("isDefaultPhoto")) {
comment.put("creatorPhotoUrl", "http://s3.amazonaws.com/pinit/default_image.png");
}
else {
comment.put("creatorPhotoUrl",
ParseUser.getCurrentUser()
.getParseFile("profilePhotoThumbnail")
.getUrl());
}
comment.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if(e == null) {
relation.add(comment);
mParseNote.saveInBackground(new SaveCallback() {
@SuppressWarnings("deprecation")
@Override
public void done(ParseException e) {
if(e == null) {
mCommentsListView.setSelection(mAdapter.getCount()-1);
mNoteCommentsCount++;
mNumberOfCommentsLoaded++;
mCommentField.setText("");
mSendCommentButton.setEnabled(true);
String date = comment.getCreatedAt().toString();
mNoteComments.add(new NoteComment(
comment.getString("creatorName"),
comment.getString("commentText"),
comment.getString("creatorPhotoUrl"),
PinItUtils.getFormattedCommentCreatedAt(date),
comment.getCreatedAt().toString()));
mAdapter.notifyDataSetChanged();
mCommentsListView.post(new Runnable() {
@Override
public void run() {
mCommentsListView.setSelection(mAdapter.getCount() - 1);
}
});
mCommentsListView.setBackgroundDrawable(null);
setActivityResult();
}
else {
mSendCommentButton.setEnabled(true);
PinItUtils.createAlert("This is embarrassing",
e.getMessage(),
CommentsActivity.this);
}
}
});
}
else {
mSendCommentButton.setEnabled(true);
PinItUtils.createAlert("This is embarrassing",
"We couldn't post that comment at this moment, please try again",
CommentsActivity.this);
}
}
});
}
}
}
private void updateLikesSize() {
mShowLikesButton.setVisibility(ImageButton.VISIBLE);
if(mNoteLikesCount == 0) {
mNumberOfLikes.setBackgroundResource(R.drawable.custom_comment_button);
mShowLikesButton.setVisibility(ImageButton.INVISIBLE);
mNumberOfLikes.setText("Be the first to like this!");
}
else if(mNoteLikesCount == 1) {
mNumberOfLikes.setBackgroundResource(R.drawable.number_of_likes_background);
mNumberOfLikes.setText("1 person likes this");
}
else {
mNumberOfLikes.setBackgroundResource(R.drawable.number_of_likes_background);
mNumberOfLikes.setText(mNoteLikesCount+" people like this");
}
}
/**
* Detects when user is close to the end of the current page and starts loading the next page
* so the user will not have to wait (that much) for the next entries.
*
* @author Ognyan Bankov (ognyan.bankov@bulpros.com)
*/
public class EndlessScrollListener implements OnScrollListener {
// how many entries earlier to start loading next page
private int visibleThreshold = 5;
private int currentPage = 0;
private int previousTotal = 0;
private boolean loading = true;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
mNumberOfCommentsLoaded = totalItemCount;
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
currentPage++;
}
}
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
loading = true;
loadMoreComments();
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
public int getCurrentPage() {
return currentPage;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case DISPLAY_NOTE_LIKES:
mShowingLikes = false;
if(resultCode == RESULT_OK) {
mNumberOfLikesLoaded = data.getIntExtra("numberOfLikesLoaded", 0);
ArrayList<NoteLike> likes = data.getParcelableArrayListExtra("noteLikes");
mNoteLikes = likes;
if(mNumberOfLikesLoaded >= mNoteLikesCount) {
mNoteLikesCount = mNumberOfLikesLoaded;
updateLikesSize();
}
}
}
}
private void setActivityResult() {
Intent intent = new Intent();
intent.putExtra("userLikesNote", mUserLikesNote);
intent.putExtra("noteCommentsCount", mNoteCommentsCount);
intent.putExtra("noteLikesCount", mNoteLikesCount);
intent.putExtra("numberOfCommentsLoaded", mNumberOfCommentsLoaded);
intent.putParcelableArrayListExtra("noteComments", mNoteComments);
setResult(RESULT_OK, intent);
}
private void loadMoreComments() {
ParseQuery commentsQuery = mParseNote.getRelation("comments").getQuery();
commentsQuery.setLimit(10);
commentsQuery.setSkip(mNumberOfCommentsLoaded);
commentsQuery.addAscendingOrder("createdAt");
commentsQuery.findInBackground(new FindCallback() {
@SuppressWarnings("deprecation")
@SuppressLint("SimpleDateFormat")
@Override
public void done(List<ParseObject> objects, ParseException e) {
if(e == null) {
for(ParseObject comment: objects) {
String date = comment.getCreatedAt().toString();
NoteComment newComment = new NoteComment(
comment.getString("creatorName"),
comment.getString("commentText"),
comment.getString("creatorPhotoUrl"),
PinItUtils.getFormattedCommentCreatedAt(date),
comment.getCreatedAt().toString());
if(!mNoteComments.contains(newComment)) {
mNoteComments.add(newComment);
mNumberOfCommentsLoaded++;
mNoteCommentsCount++;
setActivityResult();
}
if(mCommentsListView.getBackground() != null) {
mCommentsListView.setBackgroundDrawable(null);
}
}
mAdapter.notifyDataSetChanged();
}
else {
PinItUtils.createAlert("We're sorry",
"We couldn't load the comments for this note at this moment, please try again!",
CommentsActivity.this);
}
}
});
}
private void loadLikesInBackground() {
if(!mShowingLikes) {
ParseQuery likesQuery = mParseNote.getRelation("likes").getQuery();
likesQuery.setLimit(10);
likesQuery.setSkip(mNumberOfLikesLoaded);
likesQuery.addDescendingOrder("createdAt");
likesQuery.findInBackground(new FindCallback() {
@Override
public void done(List<ParseObject> objects, ParseException e) {
if(e == null) {
for(ParseObject like: objects) {
NoteLike newLike = new NoteLike(
like.getString("creatorName"),
like.getString("creatorPhotoUrl"),
mParseNote.getObjectId());
if(!mNoteLikes.contains(newLike)) {
mNoteLikes.add(newLike);
mNumberOfLikesLoaded++;
}
}
}
else {
//We can fail silently here because we are only pre-fetching the likes to make
//the loading time as close to zero as possible, and anyway, we will reload these
//likes in the LikesActivity if this fails and we will show an error there.
}
if(objects != null && objects.size() != 0) {
loadLikesInBackground();
}
}
});
}
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}