Added id and capcode viewing.

Visual reponse from clicking the replies text.
Quick reply through long-click.
captchafix
Florens Douwes 12 years ago
parent 28ac0dba79
commit 052acee30d
  1. 3
      Chan/res/values/dimens.xml
  2. 1
      Chan/res/values/strings.xml
  3. 16
      Chan/src/org/floens/chan/activity/BoardActivity.java
  4. 33
      Chan/src/org/floens/chan/manager/ThreadManager.java
  5. 1
      Chan/src/org/floens/chan/model/Post.java
  6. 10
      Chan/src/org/floens/chan/net/ChanReaderRequest.java
  7. 19
      Chan/src/org/floens/chan/utils/ViewUtils.java
  8. 60
      Chan/src/org/floens/chan/view/PostView.java

@ -3,7 +3,8 @@
<dimen name="post_padding">10dp</dimen> <dimen name="post_padding">10dp</dimen>
<dimen name="post_comment_padding">11dp</dimen> <dimen name="post_comment_padding">11dp</dimen>
<dimen name="post_text_padding">6dp</dimen> <dimen name="post_icon_padding">6dp</dimen>
<dimen name="thumbnail_size">70dp</dimen> <dimen name="thumbnail_size">70dp</dimen>
<dimen name="post_icon_width">24dp</dimen> <dimen name="post_icon_width">24dp</dimen>
<dimen name="post_icon_height">14dp</dimen> <dimen name="post_icon_height">14dp</dimen>

@ -87,6 +87,7 @@
<string name="post_info">Info</string> <string name="post_info">Info</string>
<string-array name="post_options"> <string-array name="post_options">
<item>Reply</item>
<item>Quote</item> <item>Quote</item>
<item>Info</item> <item>Info</item>
<item>Show clickables</item> <item>Show clickables</item>

@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.fragment.ReplyFragment;
import org.floens.chan.fragment.ThreadFragment; import org.floens.chan.fragment.ThreadFragment;
import org.floens.chan.manager.BoardManager; import org.floens.chan.manager.BoardManager;
import org.floens.chan.manager.PinnedManager; import org.floens.chan.manager.PinnedManager;
@ -207,10 +206,10 @@ public class BoardActivity extends BaseActivity implements ActionBar.OnNavigatio
return true; return true;
case R.id.action_reply: case R.id.action_reply:
if (threadPane.isOpen()) { if (threadPane.isOpen()) {
startReply(threadPane.isSlideable(), boardLoadable); boardFragment.getThreadManager().openReply(true); // todo if tablet
} else { } else {
if (threadFragment.getThreadManager().hasThread()) { 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(); 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) { private void startLoadingBoard(Loadable loadable) {
this.boardLoadable = loadable; this.boardLoadable = loadable;

@ -4,7 +4,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.activity.ReplyActivity;
import org.floens.chan.fragment.PostRepliesFragment; import org.floens.chan.fragment.PostRepliesFragment;
import org.floens.chan.fragment.ReplyFragment;
import org.floens.chan.model.Loadable; import org.floens.chan.model.Loadable;
import org.floens.chan.model.Post; import org.floens.chan.model.Post;
import org.floens.chan.model.PostLinkable; import org.floens.chan.model.PostLinkable;
@ -128,16 +130,19 @@ public class ThreadManager {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
switch(which) { switch(which) {
case 0: // Quote case 0: // Reply
openReply(true); // todo if tablet
// Pass through
case 1: // Quote
ReplyManager.getInstance().quote(post.no); ReplyManager.getInstance().quote(post.no);
break; break;
case 1: // Info case 2: // Info
showPostInfo(post); showPostInfo(post);
break; break;
case 2: // Show clickables case 3: // Show clickables
showPostLinkables(post); showPostLinkables(post);
break; break;
case 3: // Copy text case 4: // Copy text
copyText(post.comment.toString()); copyText(post.comment.toString());
break; break;
} }
@ -147,6 +152,17 @@ public class ThreadManager {
builder.create().show(); 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) { public void onPostLinkableClicked(PostLinkable linkable) {
handleLinkableSelected(linkable); handleLinkableSelected(linkable);
} }
@ -205,6 +221,10 @@ public class ThreadManager {
text += "\nCountry: " + post.countryName; text += "\nCountry: " + post.countryName;
} }
if (!TextUtils.isEmpty(post.capcode)) {
text += "\nCapcode: " + post.capcode;
}
AlertDialog dialog = new AlertDialog.Builder(activity) AlertDialog dialog = new AlertDialog.Builder(activity)
.setTitle(R.string.post_info) .setTitle(R.string.post_info)
.setMessage(text) .setMessage(text)
@ -380,8 +400,3 @@ public class ThreadManager {
public void onThumbnailClicked(Post post); public void onThumbnailClicked(Post post);
} }
} }

@ -45,6 +45,7 @@ public class Post {
public boolean closed = false; public boolean closed = false;
public String tripcode = ""; public String tripcode = "";
public String id = ""; public String id = "";
public String capcode = "";
public String country = ""; public String country = "";
public String countryName = ""; public String countryName = "";
public long time = 0; public long time = 0;

@ -78,7 +78,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
// Thread array // Thread array
while (reader.hasNext()) { while (reader.hasNext()) {
// Thread object // Thread object
list.add(readThreadObject(reader, loadable.board)); list.add(readPostObject(reader, loadable.board));
} }
reader.endArray(); reader.endArray();
} else { } else {
@ -115,7 +115,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
if (reader.nextName().equals("posts")) { if (reader.nextName().equals("posts")) {
reader.beginArray(); reader.beginArray();
list.add(readThreadObject(reader, loadable.board)); list.add(readPostObject(reader, loadable.board));
// Only consume one post // Only consume one post
while (reader.hasNext()) reader.skipValue(); while (reader.hasNext()) reader.skipValue();
@ -162,7 +162,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
reader.beginArray(); // Threads array reader.beginArray(); // Threads array
while (reader.hasNext()) { while (reader.hasNext()) {
list.add(readThreadObject(reader, loadable.board)); list.add(readPostObject(reader, loadable.board));
} }
reader.endArray(); reader.endArray();
@ -189,7 +189,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
return list; 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 post = new Post();
post.board = board; post.board = board;
@ -242,6 +242,8 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
post.countryName = reader.nextString(); post.countryName = reader.nextString();
} else if (key.equals("id")) { } else if (key.equals("id")) {
post.id = reader.nextString(); post.id = reader.nextString();
} else if (key.equals("capcode")) {
post.capcode = reader.nextString();
} else { } else {
// Unknown/ignored key // Unknown/ignored key
// log("Unknown/ignored key: " + key + "."); // log("Unknown/ignored key: " + key + ".");

@ -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();
}
}

@ -7,17 +7,18 @@ import org.floens.chan.model.Post;
import org.floens.chan.model.PostLinkable; import org.floens.chan.model.PostLinkable;
import org.floens.chan.net.ChanUrls; import org.floens.chan.net.ChanUrls;
import org.floens.chan.utils.IconCache; import org.floens.chan.utils.IconCache;
import org.floens.chan.utils.ViewUtils;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.text.style.AbsoluteSizeSpan; import android.text.style.AbsoluteSizeSpan;
import android.text.style.BackgroundColorSpan;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; 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) { public void setPost(final Post post, final ThreadManager manager) {
this.post = post; this.post = post;
this.manager = manager; this.manager = manager;
@ -116,6 +116,22 @@ public class PostView extends LinearLayout implements View.OnClickListener, View
total = TextUtils.concat(total, tripcode, " "); 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(), CharSequence relativeTime = DateUtils.getRelativeTimeSpanString(post.time * 1000L, System.currentTimeMillis(),
DateUtils.SECOND_IN_MILLIS, 0); DateUtils.SECOND_IN_MILLIS, 0);
@ -207,10 +223,7 @@ public class PostView extends LinearLayout implements View.OnClickListener, View
setClickable(true); setClickable(true);
setFocusable(true); setFocusable(true);
int[] attr = new int[] {android.R.attr.selectableItemBackground}; ViewUtils.setPressedDrawable(this);
Drawable drawable = context.obtainStyledAttributes(attr).getDrawable(0);
setBackgroundDrawable(drawable);
} }
} }
@ -224,8 +237,9 @@ public class PostView extends LinearLayout implements View.OnClickListener, View
isBuild = true; isBuild = true;
Resources resources = context.getResources(); Resources resources = context.getResources();
int postPadding = resources.getDimensionPixelSize(R.dimen.post_padding);
int commentPadding = resources.getDimensionPixelSize(R.dimen.post_comment_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 iconWidth = resources.getDimensionPixelSize(R.dimen.post_icon_width);
int iconHeight = resources.getDimensionPixelSize(R.dimen.post_icon_height); int iconHeight = resources.getDimensionPixelSize(R.dimen.post_icon_height);
int imageSize = resources.getDimensionPixelSize(R.dimen.thumbnail_size); 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); LinearLayout right = new LinearLayout(context);
right.setOrientation(VERTICAL); right.setOrientation(VERTICAL);
right.setPadding(commentPadding, commentPadding, commentPadding, commentPadding);
LinearLayout header = new LinearLayout(context); LinearLayout header = new LinearLayout(context);
header.setOrientation(HORIZONTAL); header.setOrientation(HORIZONTAL);
titleView = new TextView(context); titleView = new TextView(context);
titleView.setTextSize(14); titleView.setTextSize(14);
titleView.setPadding(0, 0, 0, textPadding); titleView.setPadding(postPadding, postPadding, postPadding, 0);
header.addView(titleView, wrapParams); header.addView(titleView, wrapParams);
right.addView(header, matchWrapParams); right.addView(header, matchWrapParams);
iconView = new LinearLayout(context); iconView = new LinearLayout(context);
iconView.setOrientation(HORIZONTAL); iconView.setOrientation(HORIZONTAL);
iconView.setPadding(0, 0, 0, textPadding); iconView.setPadding(postPadding, iconPadding, postPadding, 0);
stickyView = new ImageView(context); stickyView = new ImageView(context);
stickyView.setImageBitmap(IconCache.stickyIcon); stickyView.setImageBitmap(IconCache.stickyIcon);
@ -285,18 +298,34 @@ public class PostView extends LinearLayout implements View.OnClickListener, View
commentView = new TextView(context); commentView = new TextView(context);
commentView.setTextSize(15); commentView.setTextSize(15);
commentView.setPadding(postPadding, commentPadding, postPadding, commentPadding);
right.addView(commentView, matchWrapParams); right.addView(commentView, matchWrapParams);
repliesCountView = new TextView(context); repliesCountView = new TextView(context);
repliesCountView.setTextColor(Color.argb(255, 100, 100, 100)); repliesCountView.setTextColor(Color.argb(255, 100, 100, 100));
repliesCountView.setPadding(0, textPadding, 0, 0); repliesCountView.setPadding(postPadding, postPadding, postPadding, postPadding);
repliesCountView.setTextSize(14); repliesCountView.setTextSize(14);
ViewUtils.setPressedDrawable(repliesCountView);
right.addView(repliesCountView, matchWrapParams); right.addView(repliesCountView, wrapParams);
full.addView(right, matchWrapParams); 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) { public void onLinkableClick(PostLinkable linkable) {
@ -314,6 +343,11 @@ public class PostView extends LinearLayout implements View.OnClickListener, View
return true; return true;
} }
private static class IDColor {
public int color;
public int backgroundColor;
}
} }

Loading…
Cancel
Save