You can now see the replies to a post.

captchafix
Florens Douwes 12 years ago
parent f7a27d1dc6
commit e280d6d465
  1. BIN
      Chan/res/drawable-hdpi/ic_action_back.png
  2. BIN
      Chan/res/drawable-hdpi/ic_action_cancel.png
  3. BIN
      Chan/res/drawable-hdpi/ic_action_done.png
  4. BIN
      Chan/res/drawable-hdpi/ic_navigation_previous_item.png
  5. BIN
      Chan/res/drawable-mdpi/ic_action_back.png
  6. BIN
      Chan/res/drawable-mdpi/ic_action_cancel.png
  7. BIN
      Chan/res/drawable-mdpi/ic_action_done.png
  8. BIN
      Chan/res/drawable-mdpi/ic_navigation_previous_item.png
  9. BIN
      Chan/res/drawable-xhdpi/ic_action_back.png
  10. BIN
      Chan/res/drawable-xhdpi/ic_action_cancel.png
  11. BIN
      Chan/res/drawable-xhdpi/ic_action_done.png
  12. BIN
      Chan/res/drawable-xhdpi/ic_navigation_previous_item.png
  13. BIN
      Chan/res/drawable-xxhdpi/ic_action_back.png
  14. BIN
      Chan/res/drawable-xxhdpi/ic_action_cancel.png
  15. BIN
      Chan/res/drawable-xxhdpi/ic_action_done.png
  16. BIN
      Chan/res/drawable-xxhdpi/ic_navigation_previous_item.png
  17. 59
      Chan/res/layout/post_replies.xml
  18. 3
      Chan/res/values/dimens.xml
  19. 7
      Chan/res/values/strings.xml
  20. 7
      Chan/src/org/floens/chan/adapter/PostAdapter.java
  21. 6
      Chan/src/org/floens/chan/entity/Pin.java
  22. 27
      Chan/src/org/floens/chan/entity/Post.java
  23. 72
      Chan/src/org/floens/chan/fragment/PostPopupFragment.java
  24. 122
      Chan/src/org/floens/chan/fragment/PostRepliesFragment.java
  25. 3
      Chan/src/org/floens/chan/fragment/ThreadFragment.java
  26. 103
      Chan/src/org/floens/chan/manager/ThreadManager.java
  27. 27
      Chan/src/org/floens/chan/net/ThreadLoader.java
  28. 42
      Chan/src/org/floens/chan/view/PostView.java

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="320dp"
android:minHeight="200dp"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal"
android:divider="?android:attr/dividerVertical"
android:showDividers="middle"
android:dividerPadding="12dp">
<FrameLayout
style="?android:actionButtonStyle"
android:id="@+id/replies_back"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<TextView style="?android:actionBarTabTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingRight="20dp"
android:drawableLeft="@drawable/ic_action_back"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:text="@string/post_replies_back" />
</FrameLayout>
<FrameLayout
style="?android:actionButtonStyle"
android:id="@+id/replies_close"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<TextView style="?android:actionBarTabTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingRight="20dp"
android:drawableLeft="@drawable/ic_action_done"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:text="@string/post_replies_close" />
</FrameLayout>
</LinearLayout>
<ListView
android:id="@+id/post_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

@ -9,9 +9,6 @@
<dimen name="post_icon_height">14dp</dimen>
<dimen name="post_max_height">200dp</dimen>
<dimen name="post_popup_min_width">200dp</dimen>
<dimen name="post_popup_min_height">100dp</dimen>
<dimen name="about_text_padding">11dp</dimen>
<dimen name="image_popup_padding">8dp</dimen>

@ -80,11 +80,14 @@
<string name="open_unknown_title">Unsupported link</string>
<string name="open_unknown">Chan can\'t open this link. Opening it in your browser instead.</string>
<string name="post_replies_back">Back</string>
<string name="post_replies_close">Close</string>
<string name="post_info">Info</string>
<string-array name="post_options">
<item>Show clickables</item>
<item>Info</item>
<item>Quote</item>
<item>Info</item>
<item>Show clickables</item>
<item>Copy text</item>
</string-array>
</resources>

@ -1,6 +1,7 @@
package org.floens.chan.adapter;
import java.util.ArrayList;
import java.util.List;
import org.floens.chan.R;
import org.floens.chan.entity.Post;
@ -21,7 +22,7 @@ public class PostAdapter extends BaseAdapter {
private final ThreadManager threadManager;
private boolean endOfLine;
private int count = 0;
private final ArrayList<Post> postList = new ArrayList<Post>();
private final List<Post> postList = new ArrayList<Post>();
public PostAdapter(Context activity, ThreadManager threadManager) {
this.activity = activity;
@ -84,14 +85,14 @@ public class PostAdapter extends BaseAdapter {
}
}
public void addToList(ArrayList<Post> list){
public void addToList(List<Post> list){
count += list.size();
postList.addAll(list);
notifyDataSetChanged();
}
public ArrayList<Post> getList() {
public List<Post> getList() {
return postList;
}

@ -1,6 +1,7 @@
package org.floens.chan.entity;
import java.util.ArrayList;
import java.util.List;
import org.floens.chan.net.ThreadLoader;
import org.floens.chan.net.ThreadLoader.ThreadLoaderListener;
@ -11,12 +12,11 @@ public class Pin {
public Type type = Type.THREAD;
public Loadable loadable = new Loadable("", -1);
private int count;
private int newCount;
private final boolean watch = true;
private boolean error = false;
private ArrayList<Post> postList = new ArrayList<Post>();
private List<Post> postList = new ArrayList<Post>();
public ThreadLoader threadLoader = new ThreadLoader(new ThreadLoaderListener() {
@Override
public void onError(VolleyError volleyError) {
@ -24,7 +24,7 @@ public class Pin {
}
@Override
public void onData(ArrayList<Post> result) {
public void onData(List<Post> result) {
postList = result;
int totalCount = result.size();

@ -50,8 +50,21 @@ public class Post {
public long time = 0;
public String email = "";
/**
* This post replies to the these ids
*/
public List<Integer> repliesTo = new ArrayList<Integer>();
/**
* These ids replied to this post
*/
public List<Integer> repliesFrom = new ArrayList<Integer>();
private PostView linkableListener;
public final ArrayList<PostLinkable> linkables = new ArrayList<PostLinkable>();
/**
* The PostView the Post is currently bound to.
*/
public Post() {
}
@ -166,10 +179,22 @@ public class Post {
SpannableString link = new SpannableString(anchor.text());
PostLinkable pl = new PostLinkable(this, anchor.text(), anchor.attr("href"), anchor.text().contains("://") ? Type.LINK : Type.QUOTE);
Type t = anchor.text().contains("://") ? Type.LINK : Type.QUOTE;
PostLinkable pl = new PostLinkable(this, anchor.text(), anchor.attr("href"), t);
link.setSpan(pl, 0, link.length(), 0);
linkables.add(pl);
if (t == Type.QUOTE) {
try {
// Get post id
String[] splitted = anchor.attr("href").split("#p");
if (splitted.length == 2) {
int id = Integer.parseInt(splitted[1]);
repliesTo.add(id);
}
} catch(NumberFormatException e) {}
}
total = TextUtils.concat(total, link);
} else {
// Unknown tag, add the inner part

@ -1,72 +0,0 @@
package org.floens.chan.fragment;
import org.floens.chan.R;
import org.floens.chan.entity.Post;
import org.floens.chan.manager.ThreadManager;
import org.floens.chan.view.PostView;
import android.app.DialogFragment;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ScrollView;
public class PostPopupFragment extends DialogFragment {
private Context context;
private ScrollView wrapper;
private Post post;
private ThreadManager manager;
public static PostPopupFragment newInstance(Post post, ThreadManager manager) {
PostPopupFragment fragment = new PostPopupFragment();
fragment.post = post;
fragment.manager = manager;
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE, 0);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
context = inflater.getContext();
Resources resources = context.getResources();
int minWidth = resources.getDimensionPixelSize(R.dimen.post_popup_min_width);
int minHeight = resources.getDimensionPixelSize(R.dimen.post_popup_min_height);
wrapper = new ScrollView(context);
wrapper.setMinimumWidth(minWidth);
wrapper.setMinimumHeight(minHeight);
return wrapper;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (post == null) {
throw new IllegalArgumentException("No post specified");
}
PostView postView = new PostView(getActivity());
postView.setPost(post, manager);
wrapper.addView(postView);
}
}

@ -0,0 +1,122 @@
package org.floens.chan.fragment;
import java.util.List;
import org.floens.chan.R;
import org.floens.chan.entity.Post;
import org.floens.chan.manager.ThreadManager;
import org.floens.chan.view.PostView;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
/**
* A DialogFragment that shows a list of posts. Use the newInstance method for instantiating.
*/
public class PostRepliesFragment extends DialogFragment {
private Context context;
private ListView listView;
private List<Post> posts;
private ThreadManager manager;
private boolean callback = true;
public static PostRepliesFragment newInstance(List<Post> posts, ThreadManager manager) {
PostRepliesFragment fragment = new PostRepliesFragment();
fragment.posts = posts;
fragment.manager = manager;
return fragment;
}
public void dismissNoCallback() {
callback = false;
dismiss();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE, 0);
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (callback) {
manager.onPostRepliesPop();
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup unused, Bundle savedInstanceState) {
context = inflater.getContext();
View container = inflater.inflate(R.layout.post_replies, null);
Resources resources = context.getResources();
listView = (ListView) container.findViewById(R.id.post_list);
container.findViewById(R.id.replies_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
container.findViewById(R.id.replies_close).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
manager.closeAllPostFragments();
dismiss();
}
});
return container;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (posts == null) {
// Restoring from background.
dismiss();
} else {
ArrayAdapter<Post> adapter = new ArrayAdapter<Post>(getActivity(), 0) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
PostView postView = null;
if (convertView instanceof PostView) {
postView = (PostView) convertView;
} else {
postView = new PostView(getActivity());
}
postView.setPost(getItem(position), manager);
return postView;
}
};
adapter.addAll(posts);
listView.setAdapter(adapter);
}
}
}

@ -1,6 +1,7 @@
package org.floens.chan.fragment;
import java.util.ArrayList;
import java.util.List;
import org.floens.chan.R;
import org.floens.chan.activity.BaseActivity;
@ -91,7 +92,7 @@ public class ThreadFragment extends Fragment implements ThreadListener {
}
@Override
public void onThreadLoaded(ArrayList<Post> posts) {
public void onThreadLoaded(List<Post> posts) {
if (!shown) {
shown = true;

@ -1,13 +1,14 @@
package org.floens.chan.manager;
import java.util.ArrayList;
import java.util.List;
import org.floens.chan.ChanApplication;
import org.floens.chan.R;
import org.floens.chan.entity.Loadable;
import org.floens.chan.entity.Post;
import org.floens.chan.entity.PostLinkable;
import org.floens.chan.fragment.PostPopupFragment;
import org.floens.chan.fragment.PostRepliesFragment;
import org.floens.chan.net.ThreadLoader;
import android.app.Activity;
@ -21,7 +22,6 @@ import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.Gravity;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
@ -41,7 +41,9 @@ public class ThreadManager {
private final ThreadManager.ThreadListener threadListener;
private Loadable loadable;
private boolean endOfLine = false;
private final SparseArray<Post> postsById = new SparseArray<Post>();
private final List<List<Post>> popupQueue = new ArrayList<List<Post>>();
private PostRepliesFragment currentPopupFragment;
public ThreadManager(Activity context, final ThreadListener listener) {
this.activity = context;
@ -54,11 +56,7 @@ public class ThreadManager {
}
@Override
public void onData(ArrayList<Post> result) {
for (Post post : result) {
postsById.append(post.no, post);
}
public void onData(List<Post> result) {
listener.onThreadLoaded(result);
}
});
@ -68,8 +66,8 @@ public class ThreadManager {
return loadable != null;
}
public Post getPostById(int id) {
return postsById.get(id);
public Post findPostById(int id) {
return threadLoader.getPostById(id);
}
public Loadable getLoadable() {
@ -85,7 +83,6 @@ public class ThreadManager {
public void stop() {
threadLoader.stop();
endOfLine = false;
postsById.clear();
}
public void reload() {
@ -131,14 +128,14 @@ public class ThreadManager {
@Override
public void onClick(DialogInterface dialog, int which) {
switch(which) {
case 0: // Show clickables
showPostLinkables(post);
break;
case 1: // Info
showPostInfo(post);
case 2: // Quote
case 0: // Quote
ReplyManager.getInstance().quote(post.no);
break;
case 1: // Info
showPostInfo(post);
case 2: // Show clickables
showPostLinkables(post);
break;
case 3: // Copy text
copyText(post.comment.toString());
break;
@ -252,13 +249,27 @@ public class ThreadManager {
}
}
public void showPostReplies(Post post) {
List<Post> p = new ArrayList<Post>();
for (int no : post.repliesFrom) {
Post r = findPostById(no);
if (r != null) {
p.add(r);
}
}
if (p.size() > 0) {
showPostsReplies(p);
}
}
/**
* Handle when a linkable has been clicked.
* @param linkable the selected linkable.
*/
private void handleLinkableSelected(final PostLinkable linkable) {
if (linkable.type == PostLinkable.Type.QUOTE) {
showPostPopup(linkable);
showPostReply(linkable);
} else if (linkable.type == PostLinkable.Type.LINK) {
if (ChanApplication.getPreferences().getBoolean("preference_open_link_confirmation", true)) {
AlertDialog dialog = new AlertDialog.Builder(activity)
@ -289,7 +300,7 @@ public class ThreadManager {
* show a dialog with the referenced post in it.
* @param linkable the clicked linkable.
*/
private void showPostPopup(PostLinkable linkable) {
private void showPostReply(PostLinkable linkable) {
String value = linkable.value;
Post post = null;
@ -300,14 +311,12 @@ public class ThreadManager {
if (splitted.length == 2) {
int id = Integer.parseInt(splitted[1]);
post = getPostById(id);
post = findPostById(id);
if (post != null) {
PostPopupFragment popup = PostPopupFragment.newInstance(post, this);
FragmentTransaction ft = activity.getFragmentManager().beginTransaction();
ft.add(popup, "postPopup");
ft.commitAllowingStateLoss();
List<Post> l = new ArrayList<Post>();
l.add(post);
showPostsReplies(l);
}
}
} catch(NumberFormatException e) {
@ -323,8 +332,48 @@ public class ThreadManager {
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(linkable.value)));
}
public interface ThreadListener {
public void onThreadLoaded(ArrayList<Post> result);
private void showPostsReplies(List<Post> list) {
// Post popups are now queued up, more than 32 popups on top of each other makes the system crash!
popupQueue.add(list);
if (currentPopupFragment != null) {
currentPopupFragment.dismissNoCallback();
}
PostRepliesFragment popup = PostRepliesFragment.newInstance(list, this);
FragmentTransaction ft = activity.getFragmentManager().beginTransaction();
ft.add(popup, "postPopup");
ft.commit();
currentPopupFragment = popup;
}
public void onPostRepliesPop() {
if (popupQueue.size() == 0) return;
popupQueue.remove(popupQueue.size() - 1);
if (popupQueue.size() > 0) {
PostRepliesFragment popup = PostRepliesFragment.newInstance(popupQueue.get(popupQueue.size() - 1), this);
FragmentTransaction ft = activity.getFragmentManager().beginTransaction();
ft.add(popup, "postPopup");
ft.commit();
currentPopupFragment = popup;
} else {
currentPopupFragment = null;
}
}
public void closeAllPostFragments() {
popupQueue.clear();
currentPopupFragment = null;
}
public interface ThreadListener {
public void onThreadLoaded(List<Post> result);
public void onThreadLoadError(VolleyError error);
public void onPostClicked(Post post);
public void onThumbnailClicked(Post post);

@ -1,12 +1,14 @@
package org.floens.chan.net;
import java.util.ArrayList;
import java.util.List;
import org.floens.chan.ChanApplication;
import org.floens.chan.entity.Loadable;
import org.floens.chan.entity.Post;
import android.util.Log;
import android.util.SparseArray;
import com.android.volley.Response;
import com.android.volley.ServerError;
@ -18,6 +20,7 @@ public class ThreadLoader {
private boolean stopped = false;
private boolean loading = false;
private Loadable loadable;
private final SparseArray<Post> postsById = new SparseArray<Post>();
public ThreadLoader(ThreadLoaderListener listener) {
this.listener = listener;
@ -52,9 +55,15 @@ public class ThreadLoader {
loader = null;
}
postsById.clear();
stopped = true;
}
public Post getPostById(int id) {
return postsById.get(id);
}
private ChanReaderRequest getData(Loadable loadable) {
ChanReaderRequest request = ChanReaderRequest.newInstance(loadable, new Response.Listener<ArrayList<Post>>() {
@Override
@ -76,9 +85,11 @@ public class ThreadLoader {
return request;
}
private void onData(ArrayList<Post> result) {
private void onData(List<Post> result) {
if (stopped) return;
processPosts(result);
listener.onData(result);
}
@ -95,8 +106,20 @@ public class ThreadLoader {
listener.onError(error);
}
private void processPosts(List<Post> posts) {
for (Post post : posts) {
postsById.append(post.no, post);
for (Post other : posts) {
if (other.repliesTo.contains(post.no)) {
post.repliesFrom.add(other.no);
}
}
}
}
public static abstract class ThreadLoaderListener {
public abstract void onData(ArrayList<Post> result);
public abstract void onData(List<Post> result);
public abstract void onError(VolleyError error);
}
}

@ -42,7 +42,7 @@ public class PostView extends LinearLayout implements View.OnClickListener, View
private NetworkImageView imageView;
private TextView titleView;
private TextView commentView;
private TextView repliesView;
private TextView repliesCountView;
private LinearLayout iconView;
private ImageView stickyView;
private NetworkImageView countryView;
@ -81,7 +81,7 @@ public class PostView extends LinearLayout implements View.OnClickListener, View
}
@SuppressWarnings("deprecation")
public void setPost(Post post, ThreadManager manager) {
public void setPost(final Post post, final ThreadManager manager) {
this.post = post;
this.manager = manager;
@ -162,20 +162,32 @@ public class PostView extends LinearLayout implements View.OnClickListener, View
post.setLinkableListener(null);
}
if (post.isOP && post.replies > 0 && manager.getLoadable().isBoardMode()) {
repliesView.setVisibility(View.VISIBLE);
if ((post.isOP && manager.getLoadable().isBoardMode() && post.replies > 0) || (post.repliesFrom.size() > 0)) {
repliesCountView.setVisibility(View.VISIBLE);
String text = "";
if (post.replies > 1) {
text = context.getString(R.string.multiple_replies);
} else if (post.replies == 1) {
text = context.getString(R.string.one_reply);
int count = manager.getLoadable().isBoardMode() ? post.replies : post.repliesFrom.size();
if (count > 1) {
text = count + " " + context.getString(R.string.multiple_replies);
} else if (count == 1) {
text = count + " " + context.getString(R.string.one_reply);
}
if (manager.getLoadable().isThreadMode()) {
repliesCountView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
manager.showPostReplies(post);
}
});
}
repliesView.setText(post.replies + " " + text);
repliesCountView.setText(text);
} else {
repliesView.setVisibility(View.GONE);
repliesCountView.setVisibility(View.GONE);
repliesCountView.setOnClickListener(null);
}
boolean showCountryFlag = !TextUtils.isEmpty(post.country);
@ -275,12 +287,12 @@ public class PostView extends LinearLayout implements View.OnClickListener, View
commentView.setTextSize(15);
right.addView(commentView, matchWrapParams);
repliesView = new TextView(context);
repliesView.setTextColor(Color.argb(255, 100, 100, 100));
repliesView.setPadding(0, textPadding, 0, 0);
repliesView.setTextSize(12);
repliesCountView = new TextView(context);
repliesCountView.setTextColor(Color.argb(255, 100, 100, 100));
repliesCountView.setPadding(0, textPadding, 0, 0);
repliesCountView.setTextSize(14);
right.addView(repliesView, matchWrapParams);
right.addView(repliesCountView, matchWrapParams);
full.addView(right, matchWrapParams);

Loading…
Cancel
Save