diff --git a/Chan/res/values/dimens.xml b/Chan/res/values/dimens.xml index 5fe9aa2f..92fe81a2 100644 --- a/Chan/res/values/dimens.xml +++ b/Chan/res/values/dimens.xml @@ -3,7 +3,8 @@ 10dp 11dp - 6dp + 6dp + 70dp 24dp 14dp diff --git a/Chan/res/values/strings.xml b/Chan/res/values/strings.xml index 80f3ebf6..ccf2f858 100644 --- a/Chan/res/values/strings.xml +++ b/Chan/res/values/strings.xml @@ -87,6 +87,7 @@ Info + Reply Quote Info Show clickables diff --git a/Chan/src/org/floens/chan/activity/BoardActivity.java b/Chan/src/org/floens/chan/activity/BoardActivity.java index f0286ac9..3faaa200 100644 --- a/Chan/src/org/floens/chan/activity/BoardActivity.java +++ b/Chan/src/org/floens/chan/activity/BoardActivity.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.List; import org.floens.chan.R; -import org.floens.chan.fragment.ReplyFragment; import org.floens.chan.fragment.ThreadFragment; import org.floens.chan.manager.BoardManager; import org.floens.chan.manager.PinnedManager; @@ -207,10 +206,10 @@ public class BoardActivity extends BaseActivity implements ActionBar.OnNavigatio return true; case R.id.action_reply: if (threadPane.isOpen()) { - startReply(threadPane.isSlideable(), boardLoadable); + boardFragment.getThreadManager().openReply(true); // todo if tablet } else { if (threadFragment.getThreadManager().hasThread()) { - startReply(threadPane.isSlideable(), threadLoadable); + threadFragment.getThreadManager().openReply(true); // todo if tablet } } @@ -255,17 +254,6 @@ public class BoardActivity extends BaseActivity implements ActionBar.OnNavigatio updateActionBarState(); } - private void startReply(boolean startInActivity, Loadable loadable) { - if (startInActivity) { - ReplyActivity.setLoadable(loadable); - Intent i = new Intent(this, ReplyActivity.class); - startActivity(i); - } else { - ReplyFragment reply = ReplyFragment.newInstance(loadable); - reply.show(getFragmentManager(), "replyDialog"); - } - } - private void startLoadingBoard(Loadable loadable) { this.boardLoadable = loadable; diff --git a/Chan/src/org/floens/chan/manager/ThreadManager.java b/Chan/src/org/floens/chan/manager/ThreadManager.java index 8a35d39f..cb801c53 100644 --- a/Chan/src/org/floens/chan/manager/ThreadManager.java +++ b/Chan/src/org/floens/chan/manager/ThreadManager.java @@ -4,7 +4,9 @@ import java.util.ArrayList; import java.util.List; import org.floens.chan.R; +import org.floens.chan.activity.ReplyActivity; import org.floens.chan.fragment.PostRepliesFragment; +import org.floens.chan.fragment.ReplyFragment; import org.floens.chan.model.Loadable; import org.floens.chan.model.Post; import org.floens.chan.model.PostLinkable; @@ -128,16 +130,19 @@ public class ThreadManager { @Override public void onClick(DialogInterface dialog, int which) { switch(which) { - case 0: // Quote + case 0: // Reply + openReply(true); // todo if tablet + // Pass through + case 1: // Quote ReplyManager.getInstance().quote(post.no); break; - case 1: // Info + case 2: // Info showPostInfo(post); break; - case 2: // Show clickables + case 3: // Show clickables showPostLinkables(post); break; - case 3: // Copy text + case 4: // Copy text copyText(post.comment.toString()); break; } @@ -147,6 +152,17 @@ public class ThreadManager { builder.create().show(); } + public void openReply(boolean startInActivity) { + if (startInActivity) { + ReplyActivity.setLoadable(loadable); + Intent i = new Intent(activity, ReplyActivity.class); + activity.startActivity(i); + } else { + ReplyFragment reply = ReplyFragment.newInstance(loadable); + reply.show(activity.getFragmentManager(), "replyDialog"); + } + } + public void onPostLinkableClicked(PostLinkable linkable) { handleLinkableSelected(linkable); } @@ -205,6 +221,10 @@ public class ThreadManager { text += "\nCountry: " + post.countryName; } + if (!TextUtils.isEmpty(post.capcode)) { + text += "\nCapcode: " + post.capcode; + } + AlertDialog dialog = new AlertDialog.Builder(activity) .setTitle(R.string.post_info) .setMessage(text) @@ -380,8 +400,3 @@ public class ThreadManager { public void onThumbnailClicked(Post post); } } - - - - - diff --git a/Chan/src/org/floens/chan/model/Post.java b/Chan/src/org/floens/chan/model/Post.java index e5af4f09..5b3b8ade 100644 --- a/Chan/src/org/floens/chan/model/Post.java +++ b/Chan/src/org/floens/chan/model/Post.java @@ -45,6 +45,7 @@ public class Post { public boolean closed = false; public String tripcode = ""; public String id = ""; + public String capcode = ""; public String country = ""; public String countryName = ""; public long time = 0; diff --git a/Chan/src/org/floens/chan/net/ChanReaderRequest.java b/Chan/src/org/floens/chan/net/ChanReaderRequest.java index 000adf3f..0108f4a2 100644 --- a/Chan/src/org/floens/chan/net/ChanReaderRequest.java +++ b/Chan/src/org/floens/chan/net/ChanReaderRequest.java @@ -78,7 +78,7 @@ public class ChanReaderRequest extends JsonReaderRequest> { // Thread array while (reader.hasNext()) { // Thread object - list.add(readThreadObject(reader, loadable.board)); + list.add(readPostObject(reader, loadable.board)); } reader.endArray(); } else { @@ -115,7 +115,7 @@ public class ChanReaderRequest extends JsonReaderRequest> { if (reader.nextName().equals("posts")) { reader.beginArray(); - list.add(readThreadObject(reader, loadable.board)); + list.add(readPostObject(reader, loadable.board)); // Only consume one post while (reader.hasNext()) reader.skipValue(); @@ -162,7 +162,7 @@ public class ChanReaderRequest extends JsonReaderRequest> { reader.beginArray(); // Threads array while (reader.hasNext()) { - list.add(readThreadObject(reader, loadable.board)); + list.add(readPostObject(reader, loadable.board)); } reader.endArray(); @@ -189,7 +189,7 @@ public class ChanReaderRequest extends JsonReaderRequest> { return list; } - private Post readThreadObject(JsonReader reader, String board) throws IllegalStateException, NumberFormatException, IOException { + private Post readPostObject(JsonReader reader, String board) throws IllegalStateException, NumberFormatException, IOException { Post post = new Post(); post.board = board; @@ -242,6 +242,8 @@ public class ChanReaderRequest extends JsonReaderRequest> { post.countryName = reader.nextString(); } else if (key.equals("id")) { post.id = reader.nextString(); + } else if (key.equals("capcode")) { + post.capcode = reader.nextString(); } else { // Unknown/ignored key // log("Unknown/ignored key: " + key + "."); diff --git a/Chan/src/org/floens/chan/utils/ViewUtils.java b/Chan/src/org/floens/chan/utils/ViewUtils.java new file mode 100644 index 00000000..ff9a7721 --- /dev/null +++ b/Chan/src/org/floens/chan/utils/ViewUtils.java @@ -0,0 +1,19 @@ +package org.floens.chan.utils; + +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.view.View; + +public class ViewUtils { + @SuppressWarnings("deprecation") + public static void setPressedDrawable(View view) { + TypedArray arr = view.getContext().obtainStyledAttributes( + new int[] {android.R.attr.selectableItemBackground}); + + Drawable drawable = arr.getDrawable(0); + + view.setBackgroundDrawable(drawable); + + arr.recycle(); + } +} diff --git a/Chan/src/org/floens/chan/view/PostView.java b/Chan/src/org/floens/chan/view/PostView.java index 26817b0d..583e72d5 100644 --- a/Chan/src/org/floens/chan/view/PostView.java +++ b/Chan/src/org/floens/chan/view/PostView.java @@ -7,17 +7,18 @@ import org.floens.chan.model.Post; import org.floens.chan.model.PostLinkable; import org.floens.chan.net.ChanUrls; import org.floens.chan.utils.IconCache; +import org.floens.chan.utils.ViewUtils; import android.app.Activity; import android.content.Context; import android.content.res.Resources; import android.graphics.Color; -import android.graphics.drawable.Drawable; import android.text.SpannableString; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.method.LinkMovementMethod; import android.text.style.AbsoluteSizeSpan; +import android.text.style.BackgroundColorSpan; import android.text.style.ForegroundColorSpan; import android.util.AttributeSet; import android.view.View; @@ -80,7 +81,6 @@ public class PostView extends LinearLayout implements View.OnClickListener, View } } - @SuppressWarnings("deprecation") public void setPost(final Post post, final ThreadManager manager) { this.post = post; this.manager = manager; @@ -116,6 +116,22 @@ public class PostView extends LinearLayout implements View.OnClickListener, View total = TextUtils.concat(total, tripcode, " "); } + if (!TextUtils.isEmpty(post.id)) { + SpannableString id = new SpannableString(" ID: " + post.id + " "); + IDColor c = computeIDColor(post.id); + id.setSpan(new ForegroundColorSpan(c.color), 0, id.length(), 0); + id.setSpan(new BackgroundColorSpan(c.backgroundColor), 0, id.length(), 0); + id.setSpan(new AbsoluteSizeSpan(10, true), 0, id.length(), 0); + total = TextUtils.concat(total, id, " "); + } + + if (!TextUtils.isEmpty(post.capcode)) { + SpannableString tripcode = new SpannableString("Capcode: " + post.capcode); + tripcode.setSpan(new ForegroundColorSpan(Color.argb(255, 255, 0, 0)), 0, tripcode.length(), 0); + tripcode.setSpan(new AbsoluteSizeSpan(10, true), 0, tripcode.length(), 0); + total = TextUtils.concat(total, tripcode, " "); + } + CharSequence relativeTime = DateUtils.getRelativeTimeSpanString(post.time * 1000L, System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS, 0); @@ -207,10 +223,7 @@ public class PostView extends LinearLayout implements View.OnClickListener, View setClickable(true); setFocusable(true); - int[] attr = new int[] {android.R.attr.selectableItemBackground}; - Drawable drawable = context.obtainStyledAttributes(attr).getDrawable(0); - - setBackgroundDrawable(drawable); + ViewUtils.setPressedDrawable(this); } } @@ -224,8 +237,9 @@ public class PostView extends LinearLayout implements View.OnClickListener, View isBuild = true; Resources resources = context.getResources(); + int postPadding = resources.getDimensionPixelSize(R.dimen.post_padding); int commentPadding = resources.getDimensionPixelSize(R.dimen.post_comment_padding); - int textPadding = resources.getDimensionPixelSize(R.dimen.post_text_padding); + int iconPadding = resources.getDimensionPixelSize(R.dimen.post_icon_padding); int iconWidth = resources.getDimensionPixelSize(R.dimen.post_icon_width); int iconHeight = resources.getDimensionPixelSize(R.dimen.post_icon_height); int imageSize = resources.getDimensionPixelSize(R.dimen.thumbnail_size); @@ -257,21 +271,20 @@ public class PostView extends LinearLayout implements View.OnClickListener, View LinearLayout right = new LinearLayout(context); right.setOrientation(VERTICAL); - right.setPadding(commentPadding, commentPadding, commentPadding, commentPadding); LinearLayout header = new LinearLayout(context); header.setOrientation(HORIZONTAL); titleView = new TextView(context); titleView.setTextSize(14); - titleView.setPadding(0, 0, 0, textPadding); + titleView.setPadding(postPadding, postPadding, postPadding, 0); header.addView(titleView, wrapParams); right.addView(header, matchWrapParams); iconView = new LinearLayout(context); iconView.setOrientation(HORIZONTAL); - iconView.setPadding(0, 0, 0, textPadding); + iconView.setPadding(postPadding, iconPadding, postPadding, 0); stickyView = new ImageView(context); stickyView.setImageBitmap(IconCache.stickyIcon); @@ -285,18 +298,34 @@ public class PostView extends LinearLayout implements View.OnClickListener, View commentView = new TextView(context); commentView.setTextSize(15); + commentView.setPadding(postPadding, commentPadding, postPadding, commentPadding); right.addView(commentView, matchWrapParams); repliesCountView = new TextView(context); repliesCountView.setTextColor(Color.argb(255, 100, 100, 100)); - repliesCountView.setPadding(0, textPadding, 0, 0); + repliesCountView.setPadding(postPadding, postPadding, postPadding, postPadding); repliesCountView.setTextSize(14); + ViewUtils.setPressedDrawable(repliesCountView); - right.addView(repliesCountView, matchWrapParams); + right.addView(repliesCountView, wrapParams); full.addView(right, matchWrapParams); - addView(full, wrapParams); + addView(full, matchParams); + } + + private IDColor computeIDColor(String id) { + // Stolen from the 4chan extension + int hash = post.id.hashCode(); + + int r = (hash >> 24) & 0xff; + int g = (hash >> 16) & 0xff; + int b = (hash >> 8) & 0xff; + + IDColor c = new IDColor(); + c.color = (0xff << 24) + (r << 16) + (g << 8) + b; + c.backgroundColor = ((r * 0.299f) + (g * 0.587f) + (b * 0.114f)) > 125 ? 0xff636363 : 0x00000000; + return c; } public void onLinkableClick(PostLinkable linkable) { @@ -314,6 +343,11 @@ public class PostView extends LinearLayout implements View.OnClickListener, View return true; } + + private static class IDColor { + public int color; + public int backgroundColor; + } }