Add Thread model

Contains a list of posts
Already has some other flags like closed and archived.
In the future more data will be added to Thread.
captchafix
Floens 11 years ago
parent 3679fd473b
commit ecc2790275
  1. 80
      Clover/app/src/main/java/org/floens/chan/core/loader/Loader.java
  2. 28
      Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java
  3. 14
      Clover/app/src/main/java/org/floens/chan/core/model/ChanThread.java
  4. 17
      Clover/app/src/main/java/org/floens/chan/core/watch/PinWatcher.java
  5. 3
      Clover/app/src/main/java/org/floens/chan/ui/activity/BaseActivity.java
  6. 7
      Clover/app/src/main/java/org/floens/chan/ui/activity/ChanActivity.java
  7. 58
      Clover/app/src/main/java/org/floens/chan/ui/adapter/PostAdapter.java
  8. 14
      Clover/app/src/main/java/org/floens/chan/ui/fragment/ThreadFragment.java

@ -25,6 +25,7 @@ import com.android.volley.ServerError;
import com.android.volley.VolleyError; import com.android.volley.VolleyError;
import org.floens.chan.ChanApplication; import org.floens.chan.ChanApplication;
import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Post; import org.floens.chan.core.model.Post;
import org.floens.chan.core.net.ChanReaderRequest; import org.floens.chan.core.net.ChanReaderRequest;
@ -45,11 +46,10 @@ public class Loader {
private static final int[] watchTimeouts = {10, 15, 20, 30, 60, 90, 120, 180, 240, 300, 600, 1800, 3600}; private static final int[] watchTimeouts = {10, 15, 20, 30, 60, 90, 120, 180, 240, 300, 600, 1800, 3600};
private final List<LoaderListener> listeners = new ArrayList<LoaderListener>(); private final List<LoaderListener> listeners = new ArrayList<>();
private final Loadable loadable; private final Loadable loadable;
private final SparseArray<Post> postsById = new SparseArray<Post>(); private final SparseArray<Post> postsById = new SparseArray<>();
private final List<Post> cachedPosts = new ArrayList<Post>(); private ChanThread thread;
private Post op;
private boolean destroyed = false; private boolean destroyed = false;
private boolean autoReload = false; private boolean autoReload = false;
@ -84,6 +84,9 @@ public class Loader {
if (listeners.size() == 0) { if (listeners.size() == 0) {
clearTimer(); clearTimer();
destroyed = true; destroyed = true;
if (request != null) {
request.cancel();
}
return true; return true;
} else { } else {
return false; return false;
@ -133,8 +136,7 @@ public class Loader {
} }
currentTimeout = 0; currentTimeout = 0;
cachedPosts.clear(); thread = null;
op = null;
request = getData(); request = getData();
} }
@ -186,10 +188,6 @@ public class Loader {
return loadable; return loadable;
} }
public Post getOP() {
return op;
}
/** /**
* Get the time in milliseconds until another loadMore is recommended * Get the time in milliseconds until another loadMore is recommended
* *
@ -204,8 +202,8 @@ public class Loader {
} }
} }
public List<Post> getCachedPosts() { public ChanThread getThread() {
return cachedPosts; return thread;
} }
private void setTimer(int postCount) { private void setTimer(int postCount) {
@ -255,9 +253,10 @@ public class Loader {
} }
private ChanReaderRequest getData() { private ChanReaderRequest getData() {
Logger.i(TAG, "Requested " + loadable.board + ", " + loadable.no); // Logger.i(TAG, "Requested " + loadable.board + ", " + loadable.no);
ChanReaderRequest request = ChanReaderRequest.newInstance(loadable, cachedPosts, List<Post> cached = thread == null ? new ArrayList<Post>() : thread.posts;
ChanReaderRequest request = ChanReaderRequest.newInstance(loadable, cached,
new Response.Listener<List<Post>>() { new Response.Listener<List<Post>>() {
@Override @Override
public void onResponse(List<Post> list) { public void onResponse(List<Post> list) {
@ -282,31 +281,56 @@ public class Loader {
if (destroyed) if (destroyed)
return; return;
cachedPosts.clear(); if (thread == null) {
thread = new ChanThread(new ArrayList<Post>());
if (loadable.isThreadMode()) {
cachedPosts.addAll(result);
} }
postsById.clear(); if (loadable.isThreadMode() || loadable.isCatalogMode()) {
for (Post post : result) { thread.posts.clear();
postsById.append(post.no, post); thread.posts.addAll(result);
postsById.clear();
for (Post post : result) {
postsById.append(post.no, post);
}
} else if (loadable.isBoardMode()) {
// Only add new posts
boolean flag;
for (Post post : result) {
flag = true;
for (Post cached : thread.posts) {
if (post.no == cached.no) {
flag = false;
break;
}
}
if (flag) {
thread.posts.add(post);
postsById.append(post.no, post);
}
}
} }
if (loadable.isThreadMode() && result.size() > 0) { if (loadable.isThreadMode() && thread.posts.size() > 0) {
op = result.get(0); thread.op = thread.posts.get(0);
thread.closed = thread.op.closed;
thread.archived = thread.op.archived;
} }
if (TextUtils.isEmpty(loadable.title)) { if (TextUtils.isEmpty(loadable.title)) {
if (getOP() != null) { if (thread.op != null) {
loadable.generateTitle(getOP()); loadable.generateTitle(thread.op);
} else { } else {
loadable.title = "/" + loadable.board + "/"; loadable.title = "/" + loadable.board + "/";
} }
} }
for (Post post : thread.posts) {
post.title = loadable.title;
}
for (LoaderListener l : listeners) { for (LoaderListener l : listeners) {
l.onData(result, loadable.isBoardMode()); l.onData(thread);
} }
lastLoadTime = Time.get(); lastLoadTime = Time.get();
@ -320,7 +344,7 @@ public class Loader {
if (destroyed) if (destroyed)
return; return;
cachedPosts.clear(); thread = null;
Logger.e(TAG, "Error loading " + error.getMessage(), error); Logger.e(TAG, "Error loading " + error.getMessage(), error);
@ -337,7 +361,7 @@ public class Loader {
} }
public static interface LoaderListener { public static interface LoaderListener {
public void onData(List<Post> result, boolean append); public void onData(ChanThread result);
public void onError(VolleyError error); public void onError(VolleyError error);
} }

@ -45,6 +45,7 @@ import org.floens.chan.core.loader.Loader;
import org.floens.chan.core.loader.LoaderPool; import org.floens.chan.core.loader.LoaderPool;
import org.floens.chan.core.manager.ReplyManager.DeleteListener; import org.floens.chan.core.manager.ReplyManager.DeleteListener;
import org.floens.chan.core.manager.ReplyManager.DeleteResponse; import org.floens.chan.core.manager.ReplyManager.DeleteResponse;
import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Pin; import org.floens.chan.core.model.Pin;
import org.floens.chan.core.model.Post; import org.floens.chan.core.model.Post;
@ -92,7 +93,7 @@ public class ThreadManager implements Loader.LoaderListener {
public void onStart() { public void onStart() {
if (loader != null) { if (loader != null) {
if (shouldWatch()) { if (isWatching()) {
loader.setAutoLoadMore(true); loader.setAutoLoadMore(true);
loader.requestMoreDataAndResetTimer(); loader.requestMoreDataAndResetTimer();
} }
@ -111,7 +112,7 @@ public class ThreadManager implements Loader.LoaderListener {
} }
loader = LoaderPool.getInstance().obtain(loadable, this); loader = LoaderPool.getInstance().obtain(loadable, this);
if (shouldWatch()) { if (isWatching()) {
loader.setAutoLoadMore(true); loader.setAutoLoadMore(true);
} }
} }
@ -131,11 +132,8 @@ public class ThreadManager implements Loader.LoaderListener {
} }
public void bottomPostViewed() { public void bottomPostViewed() {
if (loader != null && loader.getLoadable().isThreadMode()) { if (loader.getLoadable().isThreadMode() && loader.getThread() != null && loader.getThread().posts.size() > 0) {
List<Post> posts = loader.getCachedPosts(); loader.getLoadable().lastViewed = loader.getThread().posts.get(loader.getThread().posts.size() - 1).no;
if (posts.size() > 0) {
loader.getLoadable().lastViewed = posts.get(posts.size() - 1).no;
}
} }
Pin pin = ChanApplication.getWatchManager().findPinByLoadable(loader.getLoadable()); Pin pin = ChanApplication.getWatchManager().findPinByLoadable(loader.getLoadable());
@ -145,12 +143,12 @@ public class ThreadManager implements Loader.LoaderListener {
} }
} }
public boolean shouldWatch() { public boolean isWatching() {
if (!loader.getLoadable().isThreadMode()) { if (!loader.getLoadable().isThreadMode()) {
return false; return false;
} else if (!ChanPreferences.getThreadAutoRefresh()) { } else if (!ChanPreferences.getThreadAutoRefresh()) {
return false; return false;
} else if (loader.getCachedPosts().size() > 0 && loader.getCachedPosts().get(0).closed) { } else if (loader.getThread() != null && loader.getThread().closed) {
return false; return false;
} else { } else {
return true; return true;
@ -182,16 +180,16 @@ public class ThreadManager implements Loader.LoaderListener {
} }
@Override @Override
public void onData(List<Post> result, boolean append) { public void onData(ChanThread thread) {
if (!shouldWatch()) { if (!isWatching()) {
loader.setAutoLoadMore(false); loader.setAutoLoadMore(false);
} }
if (result.size() > 0) { if (thread.posts.size() > 0) {
lastPost = result.get(result.size() - 1).no; lastPost = thread.posts.get(thread.posts.size() - 1).no;
} }
threadManagerListener.onThreadLoaded(result, append); threadManagerListener.onThreadLoaded(thread);
} }
public boolean hasLoader() { public boolean hasLoader() {
@ -578,7 +576,7 @@ public class ThreadManager implements Loader.LoaderListener {
} }
public interface ThreadManagerListener { public interface ThreadManagerListener {
public void onThreadLoaded(List<Post> result, boolean append); public void onThreadLoaded(ChanThread thread);
public void onThreadLoadError(VolleyError error); public void onThreadLoadError(VolleyError error);

@ -0,0 +1,14 @@
package org.floens.chan.core.model;
import java.util.List;
public class ChanThread {
public List<Post> posts;
public Post op;
public boolean closed = false;
public boolean archived = false;
public ChanThread(List<Post> posts) {
this.posts = posts;
}
}

@ -22,6 +22,7 @@ import com.android.volley.VolleyError;
import org.floens.chan.ChanApplication; import org.floens.chan.ChanApplication;
import org.floens.chan.core.loader.Loader; import org.floens.chan.core.loader.Loader;
import org.floens.chan.core.loader.LoaderPool; import org.floens.chan.core.loader.LoaderPool;
import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Pin; import org.floens.chan.core.model.Pin;
import org.floens.chan.core.model.Post; import org.floens.chan.core.model.Post;
import org.floens.chan.utils.Logger; import org.floens.chan.utils.Logger;
@ -124,27 +125,23 @@ public class PinWatcher implements Loader.LoaderListener {
} }
@Override @Override
public void onData(List<Post> result, boolean append) { public void onData(ChanThread thread) {
pin.isError = false; pin.isError = false;
if (pin.thumbnailUrl == null && loader.getOP() != null && loader.getOP().hasImage) { if (pin.thumbnailUrl == null && thread.op != null && thread.op.hasImage) {
pin.thumbnailUrl = loader.getOP().thumbnailUrl; pin.thumbnailUrl = thread.op.thumbnailUrl;
}
for (Post post : result) {
post.title = pin.loadable.title;
} }
// Populate posts list // Populate posts list
posts.clear(); posts.clear();
posts.addAll(result); posts.addAll(thread.posts);
// Populate quotes list // Populate quotes list
quotes.clear(); quotes.clear();
// Get list of saved replies from this thread // Get list of saved replies from this thread
List<Post> savedReplies = new ArrayList<>(); List<Post> savedReplies = new ArrayList<>();
for (Post item : result) { for (Post item : thread.posts) {
// saved.title = pin.loadable.title; // saved.title = pin.loadable.title;
if (item.isSavedReply) { if (item.isSavedReply) {
@ -153,7 +150,7 @@ public class PinWatcher implements Loader.LoaderListener {
} }
// Now get a list of posts that have a quote to a saved reply // Now get a list of posts that have a quote to a saved reply
for (Post post : result) { for (Post post : thread.posts) {
for (Post saved : savedReplies) { for (Post saved : savedReplies) {
if (post.repliesTo.contains(saved.no)) { if (post.repliesTo.contains(saved.no)) {
quotes.add(post); quotes.add(post);

@ -48,6 +48,7 @@ import android.widget.ShareActionProvider;
import org.floens.chan.ChanApplication; import org.floens.chan.ChanApplication;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.core.manager.WatchManager; import org.floens.chan.core.manager.WatchManager;
import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Pin; import org.floens.chan.core.model.Pin;
import org.floens.chan.core.model.Post; import org.floens.chan.core.model.Post;
@ -92,7 +93,7 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
abstract public void onOpenThread(Loadable thread); abstract public void onOpenThread(Loadable thread);
abstract public void onThreadLoaded(Loadable loadable, List<Post> posts); abstract public void onThreadLoaded(ChanThread thread);
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {

@ -48,6 +48,7 @@ import org.floens.chan.core.loader.Loader;
import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.manager.BoardManager;
import org.floens.chan.core.manager.ThreadManager; import org.floens.chan.core.manager.ThreadManager;
import org.floens.chan.core.model.Board; import org.floens.chan.core.model.Board;
import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Pin; import org.floens.chan.core.model.Pin;
import org.floens.chan.core.model.Post; import org.floens.chan.core.model.Post;
@ -228,7 +229,7 @@ public class ChanActivity extends BaseActivity implements AdapterView.OnItemSele
} }
@Override @Override
public void onThreadLoaded(Loadable loadable, List<Post> posts) { public void onThreadLoaded(ChanThread thread) {
updateActionBarState(); updateActionBarState();
pinnedAdapter.notifyDataSetChanged(); pinnedAdapter.notifyDataSetChanged();
} }
@ -465,8 +466,8 @@ public class ChanActivity extends BaseActivity implements AdapterView.OnItemSele
case R.id.action_pin: case R.id.action_pin:
if (threadFragment.hasLoader()) { if (threadFragment.hasLoader()) {
Loader loader = threadFragment.getLoader(); Loader loader = threadFragment.getLoader();
if (loader.getCachedPosts().size() > 0) { if (loader != null && loader.getLoadable().isThreadMode() && loader.getThread() != null) {
ChanApplication.getWatchManager().addPin(loader.getLoadable(), loader.getCachedPosts().get(0)); ChanApplication.getWatchManager().addPin(loader.getLoadable(), loader.getThread().op);
pinDrawer.openDrawer(pinDrawerView); pinDrawer.openDrawer(pinDrawerView);
} }
} }

@ -35,6 +35,7 @@ import android.widget.TextView;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.core.loader.Loader; import org.floens.chan.core.loader.Loader;
import org.floens.chan.core.manager.ThreadManager; import org.floens.chan.core.manager.ThreadManager;
import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Post; import org.floens.chan.core.model.Post;
import org.floens.chan.ui.ScrollerRunnable; import org.floens.chan.ui.ScrollerRunnable;
@ -72,6 +73,7 @@ public class PostAdapter extends BaseAdapter implements Filterable {
private String statusMessage = null; private String statusMessage = null;
private String filter = ""; private String filter = "";
private int pendingScrollToPost = -1; private int pendingScrollToPost = -1;
private String statusPrefix = "";
public PostAdapter(Context activity, ThreadManager threadManager, AbsListView listView, PostAdapterListener listener) { public PostAdapter(Context activity, ThreadManager threadManager, AbsListView listView, PostAdapterListener listener) {
context = activity; context = activity;
@ -203,38 +205,18 @@ public class PostAdapter extends BaseAdapter implements Filterable {
notifyDataSetChanged(); notifyDataSetChanged();
} }
public void appendList(List<Post> list) { public void setThread(ChanThread thread) {
synchronized (lock) { synchronized (lock) {
boolean flag; if (thread.archived) {
for (Post post : list) { statusPrefix = context.getString(R.string.thread_archived) + " - ";
flag = true; } else if (thread.closed) {
for (Post own : sourceList) { statusPrefix = context.getString(R.string.thread_closed) + " - ";
if (post.no == own.no) {
flag = false;
break;
}
}
if (flag) {
sourceList.add(post);
}
}
if (!isFiltering()) {
displayList.clear();
displayList.addAll(sourceList);
} else { } else {
setFilter(filter); statusPrefix = "";
} }
}
notifyDataSetChanged();
}
public void setList(List<Post> list) {
synchronized (lock) {
sourceList.clear(); sourceList.clear();
sourceList.addAll(list); sourceList.addAll(thread.posts);
if (!isFiltering()) { if (!isFiltering()) {
displayList.clear(); displayList.clear();
@ -338,7 +320,7 @@ public class PostAdapter extends BaseAdapter implements Filterable {
public void init() { public void init() {
Loader loader = threadManager.getLoader(); Loader loader = threadManager.getLoader();
if (loader == null || loader.getLoadable() == null) if (loader == null)
return; return;
setGravity(Gravity.CENTER); setGravity(Gravity.CENTER);
@ -349,22 +331,12 @@ public class PostAdapter extends BaseAdapter implements Filterable {
if (error != null) { if (error != null) {
setText(error); setText(error);
} else { } else {
String prefix = ""; if (threadManager.isWatching()) {
Post op = threadManager.getLoader().getOP();
if (op != null) {
if (op.archived) {
prefix = context.getString(R.string.thread_archived) + " - ";
} else if (op.closed) {
prefix = context.getString(R.string.thread_closed) + " - ";
}
}
if (threadManager.shouldWatch()) {
long time = loader.getTimeUntilLoadMore() / 1000L; long time = loader.getTimeUntilLoadMore() / 1000L;
if (time == 0) { if (time == 0) {
setText(prefix + context.getString(R.string.thread_refresh_now)); setText(statusPrefix + context.getString(R.string.thread_refresh_now));
} else { } else {
setText(prefix + context.getString(R.string.thread_refresh_countdown, time)); setText(statusPrefix + context.getString(R.string.thread_refresh_countdown, time));
} }
new Handler().postDelayed(new Runnable() { new Handler().postDelayed(new Runnable() {
@ -377,9 +349,9 @@ public class PostAdapter extends BaseAdapter implements Filterable {
}, 1000); }, 1000);
} else { } else {
if (loader.getTimeUntilLoadMore() == 0) { if (loader.getTimeUntilLoadMore() == 0) {
setText(prefix + context.getString(R.string.thread_refresh_now)); setText(statusPrefix + context.getString(R.string.thread_refresh_now));
} else { } else {
setText(prefix + context.getString(R.string.thread_refresh_bar_inactive)); setText(statusPrefix + context.getString(R.string.thread_refresh_bar_inactive));
} }
} }

@ -48,6 +48,7 @@ import org.floens.chan.R;
import org.floens.chan.core.loader.EndOfLineException; import org.floens.chan.core.loader.EndOfLineException;
import org.floens.chan.core.loader.Loader; import org.floens.chan.core.loader.Loader;
import org.floens.chan.core.manager.ThreadManager; import org.floens.chan.core.manager.ThreadManager;
import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Post; import org.floens.chan.core.model.Post;
import org.floens.chan.ui.activity.BaseActivity; import org.floens.chan.ui.activity.BaseActivity;
@ -57,8 +58,6 @@ import org.floens.chan.ui.view.LoadView;
import org.floens.chan.utils.ThemeHelper; import org.floens.chan.utils.ThemeHelper;
import org.floens.chan.utils.Utils; import org.floens.chan.utils.Utils;
import java.util.List;
import javax.net.ssl.SSLException; import javax.net.ssl.SSLException;
public class ThreadFragment extends Fragment implements ThreadManager.ThreadManagerListener, PostAdapter.PostAdapterListener { public class ThreadFragment extends Fragment implements ThreadManager.ThreadManagerListener, PostAdapter.PostAdapterListener {
@ -218,7 +217,7 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana
} }
@Override @Override
public void onThreadLoaded(List<Post> posts, boolean append) { public void onThreadLoaded(ChanThread thread) {
if (postAdapter == null) { if (postAdapter == null) {
if (container != null) { if (container != null) {
container.setView(createView()); container.setView(createView());
@ -226,12 +225,7 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana
} }
postAdapter.setStatusMessage(null); postAdapter.setStatusMessage(null);
postAdapter.setThread(thread);
if (append) {
postAdapter.appendList(posts);
} else {
postAdapter.setList(posts);
}
if (highlightedPost >= 0) { if (highlightedPost >= 0) {
threadManager.highlightPost(highlightedPost); threadManager.highlightPost(highlightedPost);
@ -239,7 +233,7 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana
highlightedPost = -1; highlightedPost = -1;
} }
baseActivity.onThreadLoaded(loadable, posts); baseActivity.onThreadLoaded(thread);
} }
@Override @Override

Loading…
Cancel
Save