/* * Copyright 2013 Vishwa Patel * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License in the 'assets' directory of this * application or at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.vishwa.pinit; import java.util.ArrayList; import java.util.List; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.Window; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; import com.parse.CountCallback; import com.parse.DeleteCallback; import com.parse.FindCallback; import com.parse.GetCallback; import com.parse.GetDataCallback; import com.parse.ParseException; import com.parse.ParseFile; import com.parse.ParseObject; import com.parse.ParseQuery; import com.parse.ParseRelation; import com.parse.ParseUser; import com.parse.SaveCallback; public class DisplayNoteActivity extends Activity { public final static int NOTE_COMMENTS_DISPLAY = 106; public final static String NOTE_LOAD_ERROR = "Sorry, this note couldn't be loaded. It might " + "have been deleted by it's creator"; private ImageView mNotePhotoImageView; private TextView mNoteTitle; private TextView mNoteBody; private TextView mLikesAndCommentsInfo; private TextView mNoteCreatedInfo; private ImageButton mLikeButton; private ImageButton mCommentButton; private ProgressBar mProgressBar; private RelativeLayout mUserInfoLayout; private ScrollView mScrollView; private Bitmap mNotePhoto = null; protected static ParseObject mParseNote; private Note mNote; private ArrayList<NoteComment> mNoteComments = new ArrayList<NoteComment>(); private boolean mUserLikesNote = false; private boolean mShowingComments = false; private int mNumberOfCommentsLoaded = 0; private int mNoteLikesCount = 0; private int mNoteCommentsCount = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); mNote = (Note) getIntent().getExtras().getParcelable("note"); byte[] array = getIntent().getByteArrayExtra("userPhoto"); Bitmap userPhoto = Bitmap.createScaledBitmap( BitmapFactory.decodeByteArray(array, 0, array.length), (int) getResources().getDimension(R.dimen.display_user_photo_radius), (int) getResources().getDimension(R.dimen.display_user_photo_radius), true); Bitmap frame = BitmapFactory.decodeResource(getResources(), R.drawable.circular_frame); frame = Bitmap.createScaledBitmap(frame, (int) getResources().getDimension(R.dimen.display_user_photo_radius), (int) getResources().getDimension(R.dimen.display_user_photo_radius), true); Canvas canvas = new Canvas(userPhoto); canvas.drawBitmap(frame, 0.0f, 0.0f, null); BitmapDrawable userPhotoDrawable = new BitmapDrawable(getResources(), userPhoto); if(mNote.getNoteImageThumbnailUrl().isEmpty()) { setContentView(R.layout.activity_display_note_alt); mNoteBody = (TextView) findViewById(R.id.display_note_body_alt); mNoteTitle = (TextView) findViewById(R.id.display_note_title_alt); mNoteCreatedInfo = (TextView) findViewById(R.id.display_note_userinfo_alt); mLikeButton = (ImageButton) findViewById(R.id.display_note_like_alt); mCommentButton = (ImageButton) findViewById(R.id.display_note_comment_alt); mLikesAndCommentsInfo = (TextView) findViewById(R.id.display_note_likes_comments_info_alt); mNoteCreatedInfo.setCompoundDrawablesWithIntrinsicBounds(userPhotoDrawable, null, null, null); mNoteTitle.setVisibility(TextView.GONE); mNoteBody.setVisibility(TextView.GONE); mLikesAndCommentsInfo.setVisibility(TextView.GONE); mLikeButton.setEnabled(false); mNoteTitle.setText(mNote.getNoteTitle()); mNoteTitle.setVisibility(TextView.VISIBLE); mNoteCreatedInfo.setText("Created by "+mNote.getNoteCreator()+" on "+mNote.getNoteCreatedAt()); mNoteCreatedInfo.setVisibility(TextView.VISIBLE); if(!mNote.getNoteBody().isEmpty()) { mNoteBody.setText(mNote.getNoteBody()); mNoteBody.setVisibility(TextView.VISIBLE); } } else { setContentView(R.layout.activity_display_note); mNotePhotoImageView = (ImageView) findViewById(R.id.display_note_photo); mProgressBar = (ProgressBar) findViewById(R.id.display_note_progressbar); mNoteBody = (TextView) findViewById(R.id.display_note_body); mNoteTitle = (TextView) findViewById(R.id.display_note_title); mNoteCreatedInfo = (TextView) findViewById(R.id.display_note_userinfo); mLikeButton = (ImageButton) findViewById(R.id.display_note_like); mCommentButton = (ImageButton) findViewById(R.id.display_note_comment); mLikesAndCommentsInfo = (TextView) findViewById(R.id.display_note_likes_comments_info); mUserInfoLayout = (RelativeLayout) findViewById(R.id.display_note_userinfo_layout); mScrollView = (ScrollView) findViewById(R.id.display_scroll_layout); mNoteCreatedInfo.setCompoundDrawablesWithIntrinsicBounds(userPhotoDrawable, null, null, null); mNotePhotoImageView.setVisibility(ImageView.GONE); mNoteTitle.setVisibility(TextView.GONE); mNoteBody.setVisibility(TextView.GONE); mLikesAndCommentsInfo.setVisibility(TextView.GONE); mUserInfoLayout.setVisibility(RelativeLayout.GONE); mLikeButton.setEnabled(false); } ParseQuery query = new ParseQuery("Note"); query.getInBackground(mNote.getNoteId(), new GetCallback() { @Override public void done(final ParseObject object, ParseException e) { if(e == null) { mParseNote = object; loadLikesAndCommentsCounts(); loadUserLikePreference(); loadCommentsInBackground(); if(!mNote.getNoteImageThumbnailUrl().isEmpty()) { ParseFile notePhotoFile = mParseNote.getParseFile("notePhoto"); mProgressBar.setVisibility(ProgressBar.VISIBLE); notePhotoFile.getDataInBackground(new GetDataCallback() { @Override public void done(byte[] data, ParseException e) { if(e == null) { mNotePhoto = BitmapFactory.decodeByteArray(data, 0, data.length); mProgressBar.setVisibility(ProgressBar.GONE); mNotePhotoImageView.setAdjustViewBounds(true); mNotePhotoImageView.setImageBitmap(mNotePhoto); mNoteTitle.setText(mNote.getNoteTitle()); mNoteCreatedInfo.setText("Created by "+mNote.getNoteCreator()+ " on "+mNote.getNoteCreatedAt()); mNotePhotoImageView.setVisibility(ImageView.VISIBLE); mLikesAndCommentsInfo.setVisibility(TextView.VISIBLE); mNoteTitle.setVisibility(TextView.VISIBLE); mUserInfoLayout.setVisibility(RelativeLayout.VISIBLE); if(!mNote.getNoteBody().isEmpty()) { mNoteBody.setText(mNote.getNoteBody()); mNoteBody.setVisibility(TextView.VISIBLE); } ViewTreeObserver viewObserver = mScrollView.getViewTreeObserver(); viewObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @SuppressWarnings("deprecation") @Override public void onGlobalLayout() { if(mScrollView.canScrollVertically(1)) { mScrollView.post(new Runnable() { public void run() { int halfWay = mScrollView.getHeight()/2; mScrollView.scrollTo(0, halfWay); } }); } mScrollView.getViewTreeObserver().removeGlobalOnLayoutListener(this); } }); } } }); } } else { Toast.makeText(getApplicationContext(), NOTE_LOAD_ERROR, Toast.LENGTH_LONG).show(); finish(); } } }); mLikesAndCommentsInfo.setOnClickListener(new OnCommentClickListener()); mCommentButton.setOnClickListener(new OnCommentClickListener()); mLikeButton.setOnClickListener(new OnLikeClickListener()); } private class OnCommentClickListener implements OnClickListener { @Override public void onClick(View v) { mShowingComments = true; Intent intent = new Intent(getApplicationContext(), CommentsActivity.class); intent.putExtra("userLikesNote", mUserLikesNote); intent.putExtra("noteLikesCount", mNoteLikesCount); intent.putExtra("noteCommentsCount", mNoteCommentsCount); intent.putExtra("numberOfCommentsLoaded", mNumberOfCommentsLoaded); intent.putParcelableArrayListExtra("noteComments", mNoteComments); startActivityForResult(intent,NOTE_COMMENTS_DISPLAY); } } private class OnLikeClickListener implements OnClickListener { @Override public void onClick(View v) { if(mUserLikesNote) { mUserLikesNote = false; mLikeButton.setImageResource(R.drawable.heart); mLikeButton.setEnabled(false); mNoteLikesCount--; updateLikesAndCommentsSize(); 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) { mLikeButton.setEnabled(true); } } }); } } }); } } }); } else { mUserLikesNote = true; mLikeButton.setImageResource(R.drawable.heart_red); mLikeButton.setEnabled(false); mNoteLikesCount++; updateLikesAndCommentsSize(); 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) { mLikeButton.setEnabled(true); } }); } } }); } } } private void loadLikesAndCommentsCounts() { ParseQuery likesCountQuery = mParseNote.getRelation("likes").getQuery(); likesCountQuery.countInBackground(new CountCallback() { @Override public void done(int count, ParseException e) { if(e == null) { mNoteLikesCount = count; ParseQuery commentsCountQuery = mParseNote.getRelation("comments").getQuery(); commentsCountQuery.countInBackground(new CountCallback() { @Override public void done(int count, ParseException e) { if(e == null) { mNoteCommentsCount = count; updateLikesAndCommentsSize(); if(mNote.getNoteImageThumbnailUrl().isEmpty()) { mLikesAndCommentsInfo.setVisibility(TextView.VISIBLE); } } } }); } } }); } private void loadUserLikePreference() { ParseQuery likeQuery = new ParseQuery("Like"); likeQuery.whereEqualTo("creator", ParseUser.getCurrentUser()); likeQuery.whereEqualTo("noteId", mParseNote.getObjectId()); likeQuery.getFirstInBackground(new GetCallback() { @Override public void done(ParseObject object, ParseException e) { mLikeButton.setEnabled(true); if(e == null && object != null) { mUserLikesNote = true; mLikeButton.setImageResource(R.drawable.heart_red); } else if(object == null) { mUserLikesNote = false; mLikeButton.setImageResource(R.drawable.heart); } } }); } private void updateLikesAndCommentsSize() { if(mNoteCommentsCount == 0 && mNoteLikesCount == 0) { mLikesAndCommentsInfo.setText("Be the first to like this!"); } else if(mNoteCommentsCount == 0) { if(mNoteLikesCount == 1) { mLikesAndCommentsInfo.setText("1 Like"); } else { mLikesAndCommentsInfo.setText(String.format("%d Likes", mNoteLikesCount)); } } else if(mNoteLikesCount == 0) { if(mNoteCommentsCount == 1) { mLikesAndCommentsInfo.setText("1 Comment"); } else { mLikesAndCommentsInfo.setText(String.format("%d Comments", mNoteCommentsCount)); } } else { if(mNoteLikesCount == 1 && mNoteCommentsCount == 1) { mLikesAndCommentsInfo.setText("1 Like \u00b7 1 Comment"); } else if(mNoteLikesCount == 1) { mLikesAndCommentsInfo.setText(String.format("1 Like \u00b7 %d Comments", mNoteCommentsCount)); } else if(mNoteCommentsCount == 1) { mLikesAndCommentsInfo.setText(String.format("%d Likes \u00b7 1 Comment", mNoteLikesCount)); } else { mLikesAndCommentsInfo.setText( String.format("%d Likes \u00b7 %d Comments", mNoteLikesCount, mNoteCommentsCount)); } } } private void loadCommentsInBackground() { if(!mShowingComments) { ParseQuery commentsQuery = mParseNote.getRelation("comments").getQuery(); commentsQuery.setLimit(10); commentsQuery.setSkip(mNumberOfCommentsLoaded); commentsQuery.addAscendingOrder("createdAt"); commentsQuery.findInBackground(new FindCallback() { @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++; } } } else { //We can fail silently here because we are only pre-fetching the comments to make //the loading time as close to zero as possible, and anyway, we will reload these //comments in the CommentsActivity if this fails and we will show an error there. } if(objects != null && objects.size() != 0) { loadCommentsInBackground(); } } }); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch(requestCode) { case NOTE_COMMENTS_DISPLAY: if(resultCode == RESULT_OK) { mUserLikesNote = data.getBooleanExtra("userLikesNote", false); mNoteLikesCount = data.getIntExtra("noteLikesCount", 0); if(mUserLikesNote) { mLikeButton.setImageResource(R.drawable.heart_red); } else { mLikeButton.setImageResource(R.drawable.heart); } mNumberOfCommentsLoaded = data.getIntExtra("numberOfCommentsLoaded", 0); if(mNoteCommentsCount < data.getIntExtra("noteCommentsCount", mNoteCommentsCount)) { mNoteCommentsCount = data.getIntExtra("noteCommentsCount", mNoteCommentsCount); } ArrayList<NoteComment> comments = data.getParcelableArrayListExtra("noteComments"); mNoteComments = comments; updateLikesAndCommentsSize(); } } } @Override protected void onDestroy() { if(mNotePhoto != null) { mNotePhoto.recycle(); mNotePhoto = null; } super.onDestroy(); } }