Fix many bugs in replies so they all appear, in the right order, and as soon as they are made.

This commit is contained in:
dosiecki 2015-06-04 17:32:58 -07:00
parent 4599f2c472
commit 01036172b3
11 changed files with 97 additions and 51 deletions

View file

@ -133,15 +133,15 @@
<LinearLayout
android:id="@+id/comment_replies_container"
android:orientation="horizontal"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<View
<View
android:id="@+id/comment_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="5dp"
style="?storyCommentDivider" />
</LinearLayout>
</LinearLayout>

View file

@ -323,6 +323,7 @@ public class BlurDatabaseHelper {
commentValues.add(comment.getValues());
for (Reply reply : comment.replies) {
reply.commentId = comment.id;
reply.id = reply.constructId();
replyValues.add(reply.getValues());
}
}
@ -334,6 +335,7 @@ public class BlurDatabaseHelper {
commentValues.add(comment.getValues());
for (Reply reply : comment.replies) {
reply.commentId = comment.id;
reply.id = reply.constructId();
replyValues.add(reply.getValues());
}
}
@ -346,6 +348,7 @@ public class BlurDatabaseHelper {
commentValues.add(comment.getValues());
for (Reply reply : comment.replies) {
reply.commentId = comment.id;
reply.id = reply.constructId();
replyValues.add(reply.getValues());
}
}
@ -965,7 +968,7 @@ public class BlurDatabaseHelper {
public List<Reply> getCommentReplies(String commentId) {
String[] selArgs = new String[] {commentId};
String selection = DatabaseConstants.REPLY_COMMENTID+ " = ?";
Cursor c = dbRO.query(DatabaseConstants.REPLY_TABLE, DatabaseConstants.REPLY_COLUMNS, selection, selArgs, null, null, DatabaseConstants.REPLY_DATE + " DESC");
Cursor c = dbRO.query(DatabaseConstants.REPLY_TABLE, null, selection, selArgs, null, null, DatabaseConstants.REPLY_DATE + " ASC");
List<Reply> replies = new ArrayList<Reply>(c.getCount());
while (c.moveToNext()) {
replies.add(Reply.fromCursor(c));
@ -974,6 +977,16 @@ public class BlurDatabaseHelper {
return replies;
}
public void replyToComment(String storyId, String feedId, String commentUserId, String replyText) {
Reply reply = new Reply();
reply.commentId = Comment.constructId(storyId, feedId, commentUserId);
reply.text = replyText;
reply.userId = PrefsUtils.getUserDetails(context).id;
reply.date = new Date();
reply.id = reply.constructId();
synchronized (RW_MUTEX) {dbRW.insertWithOnConflict(DatabaseConstants.REPLY_TABLE, null, reply.getValues(), SQLiteDatabase.CONFLICT_REPLACE);}
}
public static void closeQuietly(Cursor c) {
if (c == null) return;
try {c.close();} catch (Exception e) {;}

View file

@ -134,7 +134,8 @@ public class DatabaseConstants {
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_REPLY = "reply";
public static final String ACTION_COMMENT_TEXT = "comment_text";
public static final String ACTION_STORY_HASH = "story_hash";
public static final String ACTION_FEED_ID = "feed_id";
public static final String ACTION_INCLUDE_OLDER = "include_older";
@ -275,7 +276,8 @@ public class DatabaseConstants {
ACTION_UNSHARE + INTEGER + " DEFAULT 0, " +
ACTION_LIKE_COMMENT + INTEGER + " DEFAULT 0, " +
ACTION_UNLIKE_COMMENT + INTEGER + " DEFAULT 0, " +
ACTION_COMMENT + TEXT + ", " +
ACTION_REPLY + INTEGER + " DEFAULT 0, " +
ACTION_COMMENT_TEXT + TEXT + ", " +
ACTION_STORY_HASH + TEXT + ", " +
ACTION_FEED_ID + TEXT + ", " +
ACTION_INCLUDE_OLDER + INTEGER + ", " +
@ -294,10 +296,6 @@ public class DatabaseConstants {
SOCIAL_FEED_ID, SOCIAL_FEED_USERNAME, SOCIAL_FEED_TITLE, SOCIAL_FEED_ICON, SOCIAL_FEED_POSITIVE_COUNT, SOCIAL_FEED_NEUTRAL_COUNT, SOCIAL_FEED_NEGATIVE_COUNT
};
public static final String[] REPLY_COLUMNS = {
REPLY_COMMENTID, REPLY_DATE, REPLY_ID, REPLY_SHORTDATE, REPLY_TEXT, REPLY_USERID
};
public static final String SUM_STORY_TOTAL = "storyTotal";
private static String STORY_SUM_TOTAL = " CASE " +
"WHEN MAX(" + STORY_INTELLIGENCE_AUTHORS + "," + STORY_INTELLIGENCE_TAGS + "," + STORY_INTELLIGENCE_TITLE + ") > 0 " +

View file

@ -76,7 +76,7 @@ public class Comment implements Serializable {
}
public static String constructId(String storyId, String feedId, String userId) {
return TextUtils.concat(storyId, feedId, userId).toString();
return TextUtils.concat(feedId, storyId, userId).toString();
}
}

View file

@ -4,6 +4,7 @@ import java.util.Date;
import android.content.ContentValues;
import android.database.Cursor;
import android.text.TextUtils;
import com.google.gson.annotations.SerializedName;
import com.newsblur.database.DatabaseConstants;
@ -24,6 +25,7 @@ public class Reply {
@SerializedName("date")
public Date date;
// NB: this is the commentId that we generate, not the API one
public String commentId;
public ContentValues getValues() {
@ -47,4 +49,9 @@ public class Reply {
reply.userId = cursor.getString(cursor.getColumnIndex(DatabaseConstants.REPLY_USERID));
return reply;
}
}
// construct a string we can internally use as a PK
public String constructId() {
return TextUtils.concat(commentId, "_", Long.toString(date.getTime())).toString();
}
}

View file

@ -15,6 +15,7 @@ import android.widget.Toast;
import com.newsblur.R;
import com.newsblur.domain.Story;
import com.newsblur.network.APIManager;
import com.newsblur.util.FeedUtils;
public class ReplyDialogFragment extends DialogFragment {
@ -25,9 +26,6 @@ public class ReplyDialogFragment extends DialogFragment {
private String commentUserId, commentUsername;
private Story story;
private APIManager apiManager;
public static ReplyDialogFragment newInstance(final Story story, final String commentUserId, final String commentUsername) {
ReplyDialogFragment frag = new ReplyDialogFragment();
Bundle args = new Bundle();
@ -40,17 +38,14 @@ public class ReplyDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
story = (Story) getArguments().getSerializable(STORY);
commentUserId = getArguments().getString(COMMENT_USER_ID);
commentUsername = getArguments().getString(COMMENT_USERNAME);
final Activity activity = getActivity();
apiManager = new APIManager(activity);
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
final String shareString = getResources().getString(R.string.reply_to);
String shareString = getResources().getString(R.string.reply_to);
builder.setTitle(String.format(shareString, getArguments().getString(COMMENT_USERNAME)));
LayoutInflater layoutInflater = LayoutInflater.from(activity);
@ -61,23 +56,7 @@ public class ReplyDialogFragment extends DialogFragment {
builder.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... arg) {
return apiManager.replyToComment(story.id, story.feedId, commentUserId, reply.getText().toString());
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
Toast.makeText(activity, R.string.replied, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(activity, R.string.error_replying, Toast.LENGTH_LONG).show();
}
ReplyDialogFragment.this.dismiss();
};
}.execute();
FeedUtils.replyToComment(story.id, story.feedId, commentUserId, reply.getText().toString(), activity);
}
});
builder.setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {

View file

@ -177,8 +177,10 @@ public class SetupCommentSectionTask extends AsyncTask<Void, Void, Void> {
replyUsername.setText(R.string.unknown_user);
}
TextView replySharedDate = (TextView) replyView.findViewById(R.id.reply_shareddate);
replySharedDate.setText(reply.shortDate + " ago");
if (reply.shortDate != null) {
TextView replySharedDate = (TextView) replyView.findViewById(R.id.reply_shareddate);
replySharedDate.setText(reply.shortDate + " ago");
}
((LinearLayout) commentView.findViewById(R.id.comment_replies_container)).addView(replyView);
}

View file

@ -466,14 +466,14 @@ public class APIManager {
return response.getResponse(gson, NewsBlurResponse.class);
}
public boolean replyToComment(String storyId, String storyFeedId, String commentUserId, String reply) {
public NewsBlurResponse replyToComment(String storyId, String storyFeedId, String commentUserId, String reply) {
ContentValues values = new ContentValues();
values.put(APIConstants.PARAMETER_STORYID, storyId);
values.put(APIConstants.PARAMETER_STORY_FEEDID, storyFeedId);
values.put(APIConstants.PARAMETER_COMMENT_USERID, commentUserId);
values.put(APIConstants.PARAMETER_REPLY_TEXT, reply);
final APIResponse response = post(APIConstants.URL_REPLY_TO, values);
return (!response.isError());
APIResponse response = post(APIConstants.URL_REPLY_TO, values);
return response.getResponse(gson, NewsBlurResponse.class);
}
public boolean addFeed(String feedUrl, String folderName) {

View file

@ -5,6 +5,7 @@ import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import android.text.TextUtils;
import android.util.Log;
@ -15,8 +16,15 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
public class DateStringTypeAdapter implements JsonDeserializer<Date> {
// 2012-07-23 02:43:02
private final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private final DateFormat df;
public DateStringTypeAdapter() {
// API sends dates like 2012-07-23 02:43:02
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// API doesn't indicate TZ, but it is UTC
df.setTimeZone(TimeZone.getTimeZone("UTC"));
}
@Override
public Date deserialize(JsonElement element, Type type, JsonDeserializationContext arg2) throws JsonParseException {

View file

@ -227,6 +227,14 @@ public class FeedUtils {
NbActivity.updateAllActivities(true);
triggerSync(context);
}
public static void replyToComment(String storyId, String feedId, String commentUserId, String replyText, Context context) {
ReadingAction ra = ReadingAction.replyToComment(storyId, feedId, commentUserId, replyText);
dbHelper.enqueueAction(ra);
ra.doLocal(dbHelper);
NbActivity.updateAllActivities(true);
triggerSync(context);
}
public static FeedSet feedSetFromFolderName(String folderName) {
return FeedSet.folder(folderName, getFeedIdsRecursive(folderName));

View file

@ -33,7 +33,7 @@ public class ReadingAction {
private String storyId;
private String feedId;
private String sourceUserId;
private String commentText;
private String commentReplyText; // used for both comments and replies
private String commentUserId;
private ReadingAction() {
@ -77,14 +77,14 @@ public class ReadingAction {
return ra;
}
public static ReadingAction shareStory(String hash, String storyId, String feedId, String sourceUserId, String commentText) {
public static ReadingAction shareStory(String hash, String storyId, String feedId, String sourceUserId, String commentReplyText) {
ReadingAction ra = new ReadingAction();
ra.type = ActionType.SHARE;
ra.storyHash = hash;
ra.storyId = storyId;
ra.feedId = feedId;
ra.sourceUserId = sourceUserId;
ra.commentText = commentText;
ra.commentReplyText = commentReplyText;
return ra;
}
@ -106,6 +106,16 @@ public class ReadingAction {
return ra;
}
public static ReadingAction replyToComment(String storyId, String feedId, String commentUserId, String commentReplyText) {
ReadingAction ra = new ReadingAction();
ra.type = ActionType.REPLY;
ra.storyId = storyId;
ra.commentUserId = commentUserId;
ra.feedId = feedId;
ra.commentReplyText = commentReplyText;
return ra;
}
public ContentValues toContentValues() {
ContentValues values = new ContentValues();
values.put(DatabaseConstants.ACTION_TIME, System.currentTimeMillis());
@ -145,7 +155,7 @@ 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, commentText);
values.put(DatabaseConstants.ACTION_COMMENT_TEXT, commentReplyText);
break;
case LIKE_COMMENT:
@ -162,6 +172,14 @@ public class ReadingAction {
values.put(DatabaseConstants.ACTION_COMMENT_ID, commentUserId);
break;
case REPLY:
values.put(DatabaseConstants.ACTION_REPLY, 1);
values.put(DatabaseConstants.ACTION_STORY_ID, storyId);
values.put(DatabaseConstants.ACTION_FEED_ID, feedId);
values.put(DatabaseConstants.ACTION_COMMENT_ID, commentUserId);
values.put(DatabaseConstants.ACTION_COMMENT_TEXT, commentReplyText);
break;
default:
throw new IllegalStateException("cannot serialise uknown type of action.");
@ -202,7 +220,7 @@ 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.commentText = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_COMMENT));
ra.commentReplyText = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_COMMENT_TEXT));
} 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));
@ -213,6 +231,12 @@ public class ReadingAction {
ra.storyId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_STORY_ID));
ra.feedId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_FEED_ID));
ra.commentUserId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_COMMENT_ID));
} else if (c.getInt(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_REPLY)) == 1) {
ra.type = ActionType.REPLY;
ra.storyId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_STORY_ID));
ra.feedId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_FEED_ID));
ra.commentUserId = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_COMMENT_ID));
ra.commentReplyText = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_COMMENT_TEXT));
} else {
throw new IllegalStateException("cannot deserialise uknown type of action.");
}
@ -243,7 +267,7 @@ public class ReadingAction {
return apiManager.markStoryAsUnstarred(storyHash);
case SHARE:
return apiManager.shareStory(storyId, feedId, commentText, sourceUserId);
return apiManager.shareStory(storyId, feedId, commentReplyText, sourceUserId);
case LIKE_COMMENT:
return apiManager.favouriteComment(storyId, commentUserId, feedId);
@ -251,6 +275,9 @@ public class ReadingAction {
case UNLIKE_COMMENT:
return apiManager.unFavouriteComment(storyId, commentUserId, feedId);
case REPLY:
return apiManager.replyToComment(storyId, feedId, commentUserId, commentReplyText);
default:
}
@ -286,8 +313,8 @@ public class ReadingAction {
case SHARE:
dbHelper.setStoryShared(storyHash);
if (!TextUtils.isEmpty(commentText)) {
dbHelper.insertUpdateComment(storyId, feedId, commentText);
if (!TextUtils.isEmpty(commentReplyText)) {
dbHelper.insertUpdateComment(storyId, feedId, commentReplyText);
}
break;
@ -299,6 +326,10 @@ public class ReadingAction {
dbHelper.setCommentLiked(storyId, commentUserId, feedId, false);
break;
case REPLY:
dbHelper.replyToComment(storyId, feedId, commentUserId, commentReplyText);
break;
default:
// not all actions have these, which is fine
}