From ea706716444ae1c81b5e6c7a13d28a94c0dabdf9 Mon Sep 17 00:00:00 2001 From: dosiecki Date: Wed, 3 Jun 2015 00:43:58 -0700 Subject: [PATCH] Migrate more social actions to service-moderated API use, fix local display of actions before network round-trip. Implement network half of new commenting-on-raw-shares feature. (#643) --- .../newsblur/database/BlurDatabaseHelper.java | 37 ++++- .../newsblur/database/DatabaseConstants.java | 8 +- .../src/com/newsblur/domain/Comment.java | 7 +- .../src/com/newsblur/domain/Story.java | 4 + .../fragment/ReadingItemFragment.java | 15 +- .../SetupCommentSectionTask.java | 155 ++++++++++-------- .../src/com/newsblur/network/APIManager.java | 12 +- .../com/newsblur/network/LikeCommentTask.java | 77 --------- .../newsblur/network/UnLikeCommentTask.java | 77 --------- .../src/com/newsblur/util/FeedUtils.java | 16 ++ .../src/com/newsblur/util/ReadingAction.java | 77 ++++++++- 11 files changed, 234 insertions(+), 251 deletions(-) rename clients/android/NewsBlur/src/com/newsblur/{network => fragment}/SetupCommentSectionTask.java (62%) delete mode 100644 clients/android/NewsBlur/src/com/newsblur/network/LikeCommentTask.java delete mode 100644 clients/android/NewsBlur/src/com/newsblur/network/UnLikeCommentTask.java diff --git a/clients/android/NewsBlur/src/com/newsblur/database/BlurDatabaseHelper.java b/clients/android/NewsBlur/src/com/newsblur/database/BlurDatabaseHelper.java index 0ddfb8706..f525ed19a 100644 --- a/clients/android/NewsBlur/src/com/newsblur/database/BlurDatabaseHelper.java +++ b/clients/android/NewsBlur/src/com/newsblur/database/BlurDatabaseHelper.java @@ -138,9 +138,13 @@ public class BlurDatabaseHelper { } public void cleanupFeedsFolders() { - synchronized (RW_MUTEX) {dbRW.delete(DatabaseConstants.FEED_TABLE, null, null);} - synchronized (RW_MUTEX) {dbRW.delete(DatabaseConstants.FOLDER_TABLE, null, null);} - synchronized (RW_MUTEX) {dbRW.delete(DatabaseConstants.SOCIALFEED_TABLE, null, null);} + synchronized (RW_MUTEX) { + dbRW.delete(DatabaseConstants.FEED_TABLE, null, null); + dbRW.delete(DatabaseConstants.FOLDER_TABLE, null, null); + dbRW.delete(DatabaseConstants.SOCIALFEED_TABLE, null, null); + dbRW.delete(DatabaseConstants.COMMENT_TABLE, null, null); + dbRW.delete(DatabaseConstants.REPLY_TABLE, null, null); + } } public void vacuum() { @@ -314,6 +318,7 @@ public class BlurDatabaseHelper { for (Story story : apiResponse.stories) { for (Comment comment : story.publicComments) { comment.storyId = story.id; + // we need a primary key for comments, so construct one comment.id = TextUtils.concat(story.id, story.feedId, comment.userId).toString(); commentValues.add(comment.getValues()); for (Reply reply : comment.replies) { @@ -323,6 +328,19 @@ public class BlurDatabaseHelper { } for (Comment comment : story.friendsComments) { comment.storyId = story.id; + // we need a primary key for comments, so construct one + comment.id = TextUtils.concat(story.id, story.feedId, comment.userId).toString(); + comment.byFriend = true; + commentValues.add(comment.getValues()); + for (Reply reply : comment.replies) { + reply.commentId = comment.id; + replyValues.add(reply.getValues()); + } + } + for (Comment comment : story.friendsShares) { + comment.isPseudo = true; + comment.storyId = story.id; + // we need a primary key for comments, so construct one comment.id = TextUtils.concat(story.id, story.feedId, comment.userId).toString(); comment.byFriend = true; commentValues.add(comment.getValues()); @@ -890,6 +908,19 @@ public class BlurDatabaseHelper { return comment; } + public void insertUpdateComment(String storyId, String feedId, String commentText) { + // we can only insert comments as the currently logged-in user + String userId = PrefsUtils.getUserDetails(context).id; + + Comment comment = new Comment(); + comment.id = TextUtils.concat(storyId, feedId, userId).toString(); + comment.storyId = storyId; + comment.userId = userId; + comment.commentText = commentText; + comment.byFriend = true; + synchronized (RW_MUTEX) {dbRW.insertWithOnConflict(DatabaseConstants.COMMENT_TABLE, null, comment.getValues(), SQLiteDatabase.CONFLICT_REPLACE);} + } + public UserProfile getUserProfile(String userId) { String[] selArgs = new String[] {userId}; String selection = DatabaseConstants.USER_USERID + " = ?"; diff --git a/clients/android/NewsBlur/src/com/newsblur/database/DatabaseConstants.java b/clients/android/NewsBlur/src/com/newsblur/database/DatabaseConstants.java index dafd77757..4ae06f76e 100644 --- a/clients/android/NewsBlur/src/com/newsblur/database/DatabaseConstants.java +++ b/clients/android/NewsBlur/src/com/newsblur/database/DatabaseConstants.java @@ -131,6 +131,8 @@ public class DatabaseConstants { public static final String ACTION_UNSAVE = "unsave"; public static final String ACTION_SHARE = "share"; public static final String ACTION_UNSHARE = "unshare"; + public static final String ACTION_LIKE_COMMENT = "like_comment"; + public static final String ACTION_UNLIKE_COMMENT = "unlike_comment"; public static final String ACTION_COMMENT = "comment"; public static final String ACTION_STORY_HASH = "story_hash"; public static final String ACTION_FEED_ID = "feed_id"; @@ -138,6 +140,7 @@ public class DatabaseConstants { public static final String ACTION_INCLUDE_NEWER = "include_newer"; public static final String ACTION_STORY_ID = "story_id"; public static final String ACTION_SOURCE_USER_ID = "source_user_id"; + public static final String ACTION_COMMENT_ID = "comment_id"; static final String FOLDER_SQL = "CREATE TABLE " + FOLDER_TABLE + " (" + FOLDER_NAME + TEXT + " PRIMARY KEY, " + @@ -268,13 +271,16 @@ public class DatabaseConstants { ACTION_UNSAVE + INTEGER + " DEFAULT 0, " + ACTION_SHARE + INTEGER + " DEFAULT 0, " + ACTION_UNSHARE + INTEGER + " DEFAULT 0, " + + ACTION_LIKE_COMMENT + INTEGER + " DEFAULT 0, " + + ACTION_UNLIKE_COMMENT + INTEGER + " DEFAULT 0, " + ACTION_COMMENT + TEXT + ", " + ACTION_STORY_HASH + TEXT + ", " + ACTION_FEED_ID + TEXT + ", " + ACTION_INCLUDE_OLDER + INTEGER + ", " + ACTION_INCLUDE_NEWER + INTEGER + ", " + ACTION_STORY_ID + TEXT + ", " + - ACTION_SOURCE_USER_ID + TEXT + + ACTION_SOURCE_USER_ID + TEXT + ", " + + ACTION_COMMENT_ID + TEXT + ")"; public static final String[] FEED_COLUMNS = { diff --git a/clients/android/NewsBlur/src/com/newsblur/domain/Comment.java b/clients/android/NewsBlur/src/com/newsblur/domain/Comment.java index 25486d6f5..6dec7f114 100644 --- a/clients/android/NewsBlur/src/com/newsblur/domain/Comment.java +++ b/clients/android/NewsBlur/src/com/newsblur/domain/Comment.java @@ -12,6 +12,7 @@ import com.newsblur.database.DatabaseConstants; public class Comment implements Serializable { private static final long serialVersionUID = -2018705258520565390L; + // we almost always override API version with sensible PK constructed by concating story, feed, and user IDs public String id; @SerializedName("comments") @@ -36,8 +37,12 @@ public class Comment implements Serializable { public String storyId; + // not vended by API, but we set it depending on which comment block of the response in which it appeared public boolean byFriend = false; + // means this "comment" is actually a text-less share, which looks a little bit different + public boolean isPseudo = false; + public ContentValues getValues() { ContentValues values = new ContentValues(); values.put(DatabaseConstants.COMMENT_DATE, date); @@ -69,4 +74,4 @@ public class Comment implements Serializable { return comment; } -} \ No newline at end of file +} diff --git a/clients/android/NewsBlur/src/com/newsblur/domain/Story.java b/clients/android/NewsBlur/src/com/newsblur/domain/Story.java index 5aaf6cd9b..c1802622c 100644 --- a/clients/android/NewsBlur/src/com/newsblur/domain/Story.java +++ b/clients/android/NewsBlur/src/com/newsblur/domain/Story.java @@ -79,6 +79,10 @@ public class Story implements Serializable { @SerializedName("friend_comments") public Comment[] friendsComments; + // these are pseudo-comments that allow replying to empty shares + @SerializedName("friend_shares") + public Comment[] friendsShares; + @SerializedName("intelligence") public Intelligence intelligence = new Intelligence(); diff --git a/clients/android/NewsBlur/src/com/newsblur/fragment/ReadingItemFragment.java b/clients/android/NewsBlur/src/com/newsblur/fragment/ReadingItemFragment.java index 832e3e917..7eef661d4 100644 --- a/clients/android/NewsBlur/src/com/newsblur/fragment/ReadingItemFragment.java +++ b/clients/android/NewsBlur/src/com/newsblur/fragment/ReadingItemFragment.java @@ -41,8 +41,6 @@ import com.newsblur.activity.Reading; import com.newsblur.domain.Classifier; import com.newsblur.domain.Story; import com.newsblur.domain.UserDetails; -import com.newsblur.network.APIManager; -import com.newsblur.network.SetupCommentSectionTask; import com.newsblur.service.NBSyncService; import com.newsblur.util.DefaultFeedView; import com.newsblur.util.FeedUtils; @@ -69,7 +67,6 @@ public class ReadingItemFragment extends NbFragment implements ClassifierDialogF public static final String TEXT_SIZE_VALUE = "textSizeChangeValue"; public Story story; private LayoutInflater inflater; - private APIManager apiManager; private ImageLoader imageLoader; private String feedColor, feedTitle, feedFade, feedBorder, feedIconUrl, faviconText; private Classifier classifier; @@ -131,7 +128,6 @@ public class ReadingItemFragment extends NbFragment implements ClassifierDialogF public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); imageLoader = ((NewsBlurApplication) getActivity().getApplicationContext()).getImageLoader(); - apiManager = new APIManager(getActivity()); story = getArguments() != null ? (Story) getArguments().getSerializable("story") : null; inflater = getActivity().getLayoutInflater(); @@ -197,11 +193,7 @@ public class ReadingItemFragment extends NbFragment implements ClassifierDialogF updateShareButton(); updateSaveButton(); - if (story.sharedUserIds.length > 0 || story.commentCount > 0 ) { - view.findViewById(R.id.reading_share_bar).setVisibility(View.VISIBLE); - view.findViewById(R.id.share_bar_underline).setVisibility(View.VISIBLE); - setupItemCommentsAndShares(view); - } + setupItemCommentsAndShares(); NonfocusScrollview scrollView = (NonfocusScrollview) view.findViewById(R.id.reading_scrollview); scrollView.registerScrollChangeListener(this.activity); @@ -296,8 +288,8 @@ public class ReadingItemFragment extends NbFragment implements ClassifierDialogF shareButton.setText(R.string.share_this); } - private void setupItemCommentsAndShares(final View view) { - new SetupCommentSectionTask(getActivity(), view, getFragmentManager(), inflater, apiManager, story, imageLoader).execute(); + private void setupItemCommentsAndShares() { + new SetupCommentSectionTask(getActivity(), view, getFragmentManager(), inflater, story, imageLoader).execute(); } private void setupItemMetadata() { @@ -452,6 +444,7 @@ public class ReadingItemFragment extends NbFragment implements ClassifierDialogF updateSaveButton(); updateShareButton(); reloadStoryContent(); + setupItemCommentsAndShares(); } private void loadOriginalText() { diff --git a/clients/android/NewsBlur/src/com/newsblur/network/SetupCommentSectionTask.java b/clients/android/NewsBlur/src/com/newsblur/fragment/SetupCommentSectionTask.java similarity index 62% rename from clients/android/NewsBlur/src/com/newsblur/network/SetupCommentSectionTask.java rename to clients/android/NewsBlur/src/com/newsblur/fragment/SetupCommentSectionTask.java index f138a57bb..621d14eb2 100644 --- a/clients/android/NewsBlur/src/com/newsblur/network/SetupCommentSectionTask.java +++ b/clients/android/NewsBlur/src/com/newsblur/fragment/SetupCommentSectionTask.java @@ -1,4 +1,4 @@ -package com.newsblur.network; +package com.newsblur.fragment; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -43,7 +43,6 @@ public class SetupCommentSectionTask extends AsyncTask { private ArrayList publicCommentViews; private ArrayList friendCommentViews; - private final APIManager apiManager; private final Story story; private final LayoutInflater inflater; @@ -54,11 +53,10 @@ public class SetupCommentSectionTask extends AsyncTask { private final FragmentManager manager; private List comments; - public SetupCommentSectionTask(final Context context, final View view, final FragmentManager manager, LayoutInflater inflater, final APIManager apiManager, final Story story, final ImageLoader imageLoader) { + public SetupCommentSectionTask(Context context, View view, FragmentManager manager, LayoutInflater inflater, Story story, ImageLoader imageLoader) { this.context = context; this.manager = manager; this.inflater = inflater; - this.apiManager = apiManager; this.story = story; this.imageLoader = imageLoader; viewHolder = new WeakReference(view); @@ -96,7 +94,10 @@ public class SetupCommentSectionTask extends AsyncTask { ImageView commentImage = (ImageView) commentView.findViewById(R.id.comment_user_image); TextView commentSharedDate = (TextView) commentView.findViewById(R.id.comment_shareddate); - commentSharedDate.setText(comment.sharedDate + " ago"); + // TODO: this uses hard-coded "ago" values, which will be wrong when reading prefetched stories + if (comment.sharedDate != null) { + commentSharedDate.setText(comment.sharedDate + " ago"); + } commentSharedDate.setTag(COMMENT_DATE_BY + comment.userId); final FlowLayout favouriteContainer = (FlowLayout) commentView.findViewById(R.id.comment_favourite_avatars); @@ -123,9 +124,9 @@ public class SetupCommentSectionTask extends AsyncTask { @Override public void onClick(View v) { if (!Arrays.asList(comment.likingUsers).contains(user.id)) { - new LikeCommentTask(context, apiManager, favouriteIcon, favouriteContainer, story.id, comment, story.feedId, user.id).execute(); + FeedUtils.likeComment(story, comment.userId, context); } else { - new UnLikeCommentTask(context, apiManager, favouriteIcon, favouriteContainer, story.id, comment, story.feedId, user.id).execute(); + FeedUtils.unlikeComment(story, comment.userId, context); } } }); @@ -204,12 +205,6 @@ public class SetupCommentSectionTask extends AsyncTask { imageLoader.displayImage(userPhoto, commentImage, 10f); } - if (comment.byFriend) { - friendCommentViews.add(commentView); - } else { - publicCommentViews.add(commentView); - } - commentImage.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { @@ -218,76 +213,100 @@ public class SetupCommentSectionTask extends AsyncTask { context.startActivity(i); } }); + + if (comment.byFriend) { + friendCommentViews.add(commentView); + } else { + publicCommentViews.add(commentView); + } } return null; } protected void onPostExecute(Void result) { - if (viewHolder.get() != null) { - FlowLayout sharedGrid = (FlowLayout) viewHolder.get().findViewById(R.id.reading_social_shareimages); - FlowLayout commentGrid = (FlowLayout) viewHolder.get().findViewById(R.id.reading_social_commentimages); + View view = viewHolder.get(); + if (view == null) return; // fragment was dismissed before we rendered - TextView friendCommentTotal = ((TextView) viewHolder.get().findViewById(R.id.reading_friend_comment_total)); - TextView publicCommentTotal = ((TextView) viewHolder.get().findViewById(R.id.reading_public_comment_total)); - - ViewUtils.setupCommentCount(context, viewHolder.get(), comments.size()); - ViewUtils.setupShareCount(context, viewHolder.get(), story.sharedUserIds.length); + if (story.sharedUserIds.length > 0 || publicCommentViews.size() > 0 || friendCommentViews.size() > 0) { + view.findViewById(R.id.reading_share_bar).setVisibility(View.VISIBLE); + view.findViewById(R.id.share_bar_underline).setVisibility(View.VISIBLE); + } else { + view.findViewById(R.id.reading_share_bar).setVisibility(View.GONE); + view.findViewById(R.id.share_bar_underline).setVisibility(View.GONE); + } - Set commentIds = new HashSet(); - for (Comment comment : comments) { - commentIds.add(comment.userId); - } + FlowLayout sharedGrid = (FlowLayout) view.findViewById(R.id.reading_social_shareimages); + FlowLayout commentGrid = (FlowLayout) view.findViewById(R.id.reading_social_commentimages); - for (String userId : story.sharedUserIds) { - if (!commentIds.contains(userId)) { - UserProfile user = FeedUtils.dbHelper.getUserProfile(userId); - if (user != null) { - ImageView image = ViewUtils.createSharebarImage(context, imageLoader, user.photoUrl, user.userId); - sharedGrid.addView(image); - } + TextView friendCommentTotal = ((TextView) view.findViewById(R.id.reading_friend_comment_total)); + TextView publicCommentTotal = ((TextView) view.findViewById(R.id.reading_public_comment_total)); + + ViewUtils.setupCommentCount(context, view, comments.size()); + ViewUtils.setupShareCount(context, view, story.sharedUserIds.length); + + Set commentIds = new HashSet(); + for (Comment comment : comments) { + commentIds.add(comment.userId); + } + + sharedGrid.removeAllViews(); + for (String userId : story.sharedUserIds) { + if (!commentIds.contains(userId)) { + UserProfile user = FeedUtils.dbHelper.getUserProfile(userId); + if (user != null) { + ImageView image = ViewUtils.createSharebarImage(context, imageLoader, user.photoUrl, user.userId); + sharedGrid.addView(image); } } + } - for (Comment comment : comments) { - UserProfile user = FeedUtils.dbHelper.getUserProfile(comment.userId); - ImageView image = ViewUtils.createSharebarImage(context, imageLoader, user.photoUrl, user.userId); - commentGrid.addView(image); - } - - if (publicCommentViews.size() > 0) { - String commentCount = context.getString(R.string.public_comment_count); - if (publicCommentViews.size() == 1) { - commentCount = commentCount.substring(0, commentCount.length() - 1); - } - publicCommentTotal.setText(String.format(commentCount, publicCommentViews.size())); - viewHolder.get().findViewById(R.id.reading_public_comment_header).setVisibility(View.VISIBLE); + commentGrid.removeAllViews(); + for (Comment comment : comments) { + UserProfile user = FeedUtils.dbHelper.getUserProfile(comment.userId); + ImageView image = ViewUtils.createSharebarImage(context, imageLoader, user.photoUrl, user.userId); + commentGrid.addView(image); + } + + if (publicCommentViews.size() > 0) { + String commentCount = context.getString(R.string.public_comment_count); + if (publicCommentViews.size() == 1) { + commentCount = commentCount.substring(0, commentCount.length() - 1); } - - if (friendCommentViews.size() > 0) { - String commentCount = context.getString(R.string.friends_comments_count); - if (friendCommentViews.size() == 1) { - commentCount = commentCount.substring(0, commentCount.length() - 1); - } - friendCommentTotal.setText(String.format(commentCount, friendCommentViews.size())); - viewHolder.get().findViewById(R.id.reading_friend_comment_header).setVisibility(View.VISIBLE); + publicCommentTotal.setText(String.format(commentCount, publicCommentViews.size())); + view.findViewById(R.id.reading_public_comment_header).setVisibility(View.VISIBLE); + } else { + view.findViewById(R.id.reading_public_comment_header).setVisibility(View.GONE); + } + + if (friendCommentViews.size() > 0) { + String commentCount = context.getString(R.string.friends_comments_count); + if (friendCommentViews.size() == 1) { + commentCount = commentCount.substring(0, commentCount.length() - 1); } + friendCommentTotal.setText(String.format(commentCount, friendCommentViews.size())); + view.findViewById(R.id.reading_friend_comment_header).setVisibility(View.VISIBLE); + } else { + view.findViewById(R.id.reading_friend_comment_header).setVisibility(View.GONE); + } - for (int i = 0; i < publicCommentViews.size(); i++) { - if (i == publicCommentViews.size() - 1) { - publicCommentViews.get(i).findViewById(R.id.comment_divider).setVisibility(View.GONE); - } - ((LinearLayout) viewHolder.get().findViewById(R.id.reading_public_comment_container)).addView(publicCommentViews.get(i)); - } - - for (int i = 0; i < friendCommentViews.size(); i++) { - if (i == friendCommentViews.size() - 1) { - friendCommentViews.get(i).findViewById(R.id.comment_divider).setVisibility(View.GONE); - } - ((LinearLayout) viewHolder.get().findViewById(R.id.reading_friend_comment_container)).addView(friendCommentViews.get(i)); - } - - } + LinearLayout publicCommentListContainer = (LinearLayout) view.findViewById(R.id.reading_public_comment_container); + publicCommentListContainer.removeAllViews(); + for (int i = 0; i < publicCommentViews.size(); i++) { + if (i == publicCommentViews.size() - 1) { + publicCommentViews.get(i).findViewById(R.id.comment_divider).setVisibility(View.GONE); + } + publicCommentListContainer.addView(publicCommentViews.get(i)); + } + + LinearLayout friendCommentListContainer = (LinearLayout) view.findViewById(R.id.reading_friend_comment_container); + friendCommentListContainer.removeAllViews(); + for (int i = 0; i < friendCommentViews.size(); i++) { + if (i == friendCommentViews.size() - 1) { + friendCommentViews.get(i).findViewById(R.id.comment_divider).setVisibility(View.GONE); + } + friendCommentListContainer.addView(friendCommentViews.get(i)); + } } } diff --git a/clients/android/NewsBlur/src/com/newsblur/network/APIManager.java b/clients/android/NewsBlur/src/com/newsblur/network/APIManager.java index b1f420713..8894bdbcf 100644 --- a/clients/android/NewsBlur/src/com/newsblur/network/APIManager.java +++ b/clients/android/NewsBlur/src/com/newsblur/network/APIManager.java @@ -448,22 +448,22 @@ public class APIManager { } } - public boolean favouriteComment(String storyId, String commentId, String feedId) { + public NewsBlurResponse favouriteComment(String storyId, String commentId, String feedId) { ContentValues values = new ContentValues(); values.put(APIConstants.PARAMETER_STORYID, storyId); values.put(APIConstants.PARAMETER_STORY_FEEDID, feedId); values.put(APIConstants.PARAMETER_COMMENT_USERID, commentId); - final APIResponse response = post(APIConstants.URL_LIKE_COMMENT, values); - return (!response.isError()); + APIResponse response = post(APIConstants.URL_LIKE_COMMENT, values); + return response.getResponse(gson, NewsBlurResponse.class); } - public Boolean unFavouriteComment(String storyId, String commentId, String feedId) { + public NewsBlurResponse unFavouriteComment(String storyId, String commentId, String feedId) { ContentValues values = new ContentValues(); values.put(APIConstants.PARAMETER_STORYID, storyId); values.put(APIConstants.PARAMETER_STORY_FEEDID, feedId); values.put(APIConstants.PARAMETER_COMMENT_USERID, commentId); - final APIResponse response = post(APIConstants.URL_UNLIKE_COMMENT, values); - return (!response.isError()); + APIResponse response = post(APIConstants.URL_UNLIKE_COMMENT, values); + return response.getResponse(gson, NewsBlurResponse.class); } public boolean replyToComment(String storyId, String storyFeedId, String commentUserId, String reply) { diff --git a/clients/android/NewsBlur/src/com/newsblur/network/LikeCommentTask.java b/clients/android/NewsBlur/src/com/newsblur/network/LikeCommentTask.java deleted file mode 100644 index 044b47026..000000000 --- a/clients/android/NewsBlur/src/com/newsblur/network/LikeCommentTask.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.newsblur.network; - -import java.lang.ref.WeakReference; - -import android.content.Context; -import android.graphics.Bitmap; -import android.os.AsyncTask; -import android.widget.ImageView; -import android.widget.Toast; - -import com.newsblur.R; -import com.newsblur.domain.Comment; -import com.newsblur.domain.UserDetails; -import com.newsblur.util.PrefsUtils; -import com.newsblur.util.UIUtils; -import com.newsblur.view.FlowLayout; - -public class LikeCommentTask extends AsyncTask{ - - final WeakReference favouriteIconViewHolder; - - private final APIManager apiManager; - private final String storyId; - private final Comment comment; - private final String feedId; - private final Context context; - private final String userId; - private Bitmap userImage; - private WeakReference favouriteAvatarHolder; - private UserDetails user; - - public LikeCommentTask(final Context context, final APIManager apiManager, final ImageView favouriteIcon, final FlowLayout favouriteAvatarLayout, final String storyId, final Comment comment, final String feedId, final String userId) { - this.apiManager = apiManager; - this.storyId = storyId; - this.comment = comment; - this.feedId = feedId; - this.context = context; - this.userId = userId; - - favouriteAvatarHolder = new WeakReference(favouriteAvatarLayout); - favouriteIconViewHolder = new WeakReference(favouriteIcon); - - userImage = PrefsUtils.getUserImage(context); - user = PrefsUtils.getUserDetails(context); - } - - @Override - protected Boolean doInBackground(Void... params) { - return apiManager.favouriteComment(storyId, comment.userId, feedId); - } - - @Override - protected void onPostExecute(Boolean result) { - if (favouriteIconViewHolder.get() != null) { - if (result.booleanValue()) { - favouriteIconViewHolder.get().setImageResource(R.drawable.have_favourite); - - if (userImage != null) { - ImageView favouriteImage = new ImageView(context); - favouriteImage.setTag(user.id); - userImage = UIUtils.roundCorners(userImage, 10f); - favouriteImage.setImageBitmap(userImage); - favouriteAvatarHolder.get().addView(favouriteImage); - } - - String[] newArray = new String[comment.likingUsers.length + 1]; - System.arraycopy(comment.likingUsers, 0, newArray, 0, comment.likingUsers.length); - newArray[newArray.length - 1] = userId; - comment.likingUsers = newArray; - - Toast.makeText(context, R.string.comment_favourited, Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(context, R.string.error_liking_comment, Toast.LENGTH_SHORT).show(); - } - } - } -} diff --git a/clients/android/NewsBlur/src/com/newsblur/network/UnLikeCommentTask.java b/clients/android/NewsBlur/src/com/newsblur/network/UnLikeCommentTask.java deleted file mode 100644 index 2df746d16..000000000 --- a/clients/android/NewsBlur/src/com/newsblur/network/UnLikeCommentTask.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.newsblur.network; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -import android.content.Context; -import android.os.AsyncTask; -import android.text.TextUtils; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; - -import com.newsblur.R; -import com.newsblur.domain.Comment; -import com.newsblur.domain.UserDetails; -import com.newsblur.util.PrefsUtils; -import com.newsblur.view.FlowLayout; - -public class UnLikeCommentTask extends AsyncTask{ - - private static final String TAG = "LikeCommentTask"; - final WeakReference favouriteIconViewHolder; - private final APIManager apiManager; - private final String storyId; - private final Comment comment; - private final String feedId; - private final Context context; - private final String userId; - private WeakReference favouriteAvatarHolder; - private UserDetails user; - - public UnLikeCommentTask(final Context context, final APIManager apiManager, final ImageView favouriteIcon, final FlowLayout favouriteAvatarContainer, final String storyId, final Comment comment, final String feedId, final String userId) { - this.apiManager = apiManager; - this.storyId = storyId; - this.comment = comment; - this.feedId = feedId; - this.context = context; - this.userId = userId; - - favouriteIconViewHolder = new WeakReference(favouriteIcon); - favouriteAvatarHolder = new WeakReference(favouriteAvatarContainer); - - user = PrefsUtils.getUserDetails(context); - } - - @Override - protected Boolean doInBackground(Void... params) { - return apiManager.unFavouriteComment(storyId, comment.userId, feedId); - } - - @Override - protected void onPostExecute(Boolean result) { - if (favouriteIconViewHolder.get() != null) { - if (result.booleanValue()) { - favouriteIconViewHolder.get().setImageResource(R.drawable.favourite); - - View v = favouriteAvatarHolder.get().findViewWithTag(user.id); - favouriteAvatarHolder.get().removeView(v); - - ArrayList likingUsers = new ArrayList(); - for (String user : comment.likingUsers) { - if (!TextUtils.equals(user, userId) && TextUtils.isEmpty(user)) { - likingUsers.add(user); - } - } - String[] newArray = new String[likingUsers.size()]; - likingUsers.toArray(newArray); - comment.likingUsers = newArray; - - Toast.makeText(context, "Removed favourite", Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(context, "Error removing favorite from comment", Toast.LENGTH_SHORT).show(); - } - } - } -} diff --git a/clients/android/NewsBlur/src/com/newsblur/util/FeedUtils.java b/clients/android/NewsBlur/src/com/newsblur/util/FeedUtils.java index c22fed32c..ee9732937 100644 --- a/clients/android/NewsBlur/src/com/newsblur/util/FeedUtils.java +++ b/clients/android/NewsBlur/src/com/newsblur/util/FeedUtils.java @@ -212,6 +212,22 @@ public class FeedUtils { triggerSync(context); } + public static void likeComment(Story story, String commentId, Context context) { + ReadingAction ra = ReadingAction.likeComment(story.id, commentId, story.feedId); + dbHelper.enqueueAction(ra); + ra.doLocal(dbHelper); + NbActivity.updateAllActivities(true); + triggerSync(context); + } + + public static void unlikeComment(Story story, String commentId, Context context) { + ReadingAction ra = ReadingAction.unlikeComment(story.id, commentId, story.feedId); + dbHelper.enqueueAction(ra); + ra.doLocal(dbHelper); + NbActivity.updateAllActivities(true); + triggerSync(context); + } + public static FeedSet feedSetFromFolderName(String folderName) { return FeedSet.folder(folderName, getFeedIdsRecursive(folderName)); } diff --git a/clients/android/NewsBlur/src/com/newsblur/util/ReadingAction.java b/clients/android/NewsBlur/src/com/newsblur/util/ReadingAction.java index c62af0bdb..bc045dca2 100644 --- a/clients/android/NewsBlur/src/com/newsblur/util/ReadingAction.java +++ b/clients/android/NewsBlur/src/com/newsblur/util/ReadingAction.java @@ -19,7 +19,10 @@ public class ReadingAction { MARK_UNREAD, SAVE, UNSAVE, - SHARE + SHARE, + REPLY, + LIKE_COMMENT, + UNLIKE_COMMENT }; private ActionType type; @@ -30,7 +33,8 @@ public class ReadingAction { private String storyId; private String feedId; private String sourceUserId; - private String comment; + private String commentText; + private String commentId; private ReadingAction() { ; // must use helpers @@ -73,14 +77,32 @@ public class ReadingAction { return ra; } - public static ReadingAction shareStory(String hash, String storyId, String feedId, String sourceUserId, String comment) { + public static ReadingAction shareStory(String hash, String storyId, String feedId, String sourceUserId, String commentText) { ReadingAction ra = new ReadingAction(); ra.type = ActionType.SHARE; ra.storyHash = hash; ra.storyId = storyId; ra.feedId = feedId; ra.sourceUserId = sourceUserId; - ra.comment = comment; + ra.commentText = commentText; + return ra; + } + + public static ReadingAction likeComment(String storyId, String commentId, String feedId) { + ReadingAction ra = new ReadingAction(); + ra.type = ActionType.LIKE_COMMENT; + ra.storyId = storyId; + ra.commentId = commentId; + ra.feedId = feedId; + return ra; + } + + public static ReadingAction unlikeComment(String storyId, String commentId, String feedId) { + ReadingAction ra = new ReadingAction(); + ra.type = ActionType.UNLIKE_COMMENT; + ra.storyId = storyId; + ra.commentId = commentId; + ra.feedId = feedId; return ra; } @@ -123,7 +145,21 @@ public class ReadingAction { values.put(DatabaseConstants.ACTION_STORY_ID, storyId); values.put(DatabaseConstants.ACTION_FEED_ID, feedId); values.put(DatabaseConstants.ACTION_SOURCE_USER_ID, sourceUserId); - values.put(DatabaseConstants.ACTION_COMMENT, comment); + values.put(DatabaseConstants.ACTION_COMMENT, commentText); + break; + + case LIKE_COMMENT: + values.put(DatabaseConstants.ACTION_LIKE_COMMENT, 1); + values.put(DatabaseConstants.ACTION_STORY_ID, storyId); + values.put(DatabaseConstants.ACTION_FEED_ID, feedId); + values.put(DatabaseConstants.ACTION_COMMENT_ID, commentId); + break; + + case UNLIKE_COMMENT: + values.put(DatabaseConstants.ACTION_UNLIKE_COMMENT, 1); + values.put(DatabaseConstants.ACTION_STORY_ID, storyId); + values.put(DatabaseConstants.ACTION_FEED_ID, feedId); + values.put(DatabaseConstants.ACTION_COMMENT_ID, commentId); break; default: @@ -166,7 +202,17 @@ public class ReadingAction { ra.storyId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_STORY_ID)); ra.feedId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_FEED_ID)); ra.sourceUserId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_SOURCE_USER_ID)); - ra.comment = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_COMMENT)); + ra.commentText = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_COMMENT)); + } else if (c.getInt(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_LIKE_COMMENT)) == 1) { + ra.type = ActionType.LIKE_COMMENT; + ra.storyId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_STORY_ID)); + ra.feedId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_FEED_ID)); + ra.commentId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_COMMENT_ID)); + } else if (c.getInt(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_UNLIKE_COMMENT)) == 1) { + ra.type = ActionType.UNLIKE_COMMENT; + ra.storyId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_STORY_ID)); + ra.feedId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_FEED_ID)); + ra.commentId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_COMMENT_ID)); } else { throw new IllegalStateException("cannot deserialise uknown type of action."); } @@ -197,7 +243,13 @@ public class ReadingAction { return apiManager.markStoryAsUnstarred(storyHash); case SHARE: - return apiManager.shareStory(storyId, feedId, comment, sourceUserId); + return apiManager.shareStory(storyId, feedId, commentText, sourceUserId); + + case LIKE_COMMENT: + return apiManager.favouriteComment(storyId, commentId, feedId); + + case UNLIKE_COMMENT: + return apiManager.unFavouriteComment(storyId, commentId, feedId); default: @@ -234,6 +286,17 @@ public class ReadingAction { case SHARE: dbHelper.setStoryShared(storyHash); + if (!TextUtils.isEmpty(commentText)) { + dbHelper.insertUpdateComment(storyId, feedId, commentText); + } + break; + + case LIKE_COMMENT: + // TODO + break; + + case UNLIKE_COMMENT: + // TODO break; default: