ThreadWatcher updates

captchafix
Florens Douwes 12 years ago
parent 75d6583ff6
commit 2c5cd1bedb
  1. 0
      Chan/res/drawable/pin_icon_blue.xml
  2. 16
      Chan/res/drawable/pin_icon_red.xml
  3. 5
      Chan/res/layout/pin_item.xml
  4. 16
      Chan/src/org/floens/chan/activity/BaseActivity.java
  5. 13
      Chan/src/org/floens/chan/adapter/PinnedAdapter.java
  6. 12
      Chan/src/org/floens/chan/database/DatabaseHelper.java
  7. 1
      Chan/src/org/floens/chan/fragment/ThreadFragment.java
  8. 33
      Chan/src/org/floens/chan/manager/PinnedManager.java
  9. 33
      Chan/src/org/floens/chan/manager/ThreadManager.java
  10. 19
      Chan/src/org/floens/chan/model/Loadable.java
  11. 41
      Chan/src/org/floens/chan/model/Pin.java
  12. 12
      Chan/src/org/floens/chan/model/Post.java
  13. 49
      Chan/src/org/floens/chan/net/ChanReaderRequest.java
  14. 21
      Chan/src/org/floens/chan/net/ThreadLoader.java
  15. 14
      Chan/src/org/floens/chan/service/PinnedService.java
  16. 61
      Chan/src/org/floens/chan/watch/PinWatcher.java

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="8dp"
android:insetTop="8dp"
android:insetRight="8dp"
android:insetBottom="8dp" >
<shape>
<solid
android:color="#FFCC0000" />
<corners
android:radius="4dp" />
</shape>
</inset>

@ -23,7 +23,8 @@
</TextView>
<FrameLayout
android:background="@drawable/pin_icon"
android:id="@+id/drawer_item_count_container"
android:background="@drawable/pin_icon_blue"
android:layout_width="48dp"
android:layout_height="48dp" >
@ -34,7 +35,7 @@
android:gravity="center"
android:textSize="16dp"
android:textColor="#fff"
android:text="99+" />
android:text="99" />
</FrameLayout>

@ -36,7 +36,7 @@ import android.widget.EditText;
import android.widget.ListView;
import android.widget.ShareActionProvider;
public abstract class BaseActivity extends Activity implements PanelSlideListener {
public abstract class BaseActivity extends Activity implements PanelSlideListener, PinnedManager.PinListener {
private final static int ACTION_OPEN_URL = 1;
protected PinnedAdapter pinnedAdapter;
@ -71,6 +71,15 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
threadPane = (SlidingPaneLayout) findViewById(R.id.pane_container);
initPane();
PinnedManager.getInstance().addPinListener(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
PinnedManager.getInstance().removePinListener(this);
}
protected void initDrawer() {
@ -134,6 +143,11 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
threadPane.openPane();
}
@Override
public void onPinsChanged() {
pinnedAdapter.notifyDataSetChanged();
}
public void addPin(Pin pin) {
if (PinnedManager.getInstance().add(pin)) {
pinnedAdapter.add(pin);

@ -11,6 +11,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -45,6 +46,18 @@ public class PinnedAdapter extends ArrayAdapter<Pin> {
view = (LinearLayout) inflater.inflate(R.layout.pin_item, null);
((TextView) view.findViewById(R.id.drawer_item_text)).setText(item.loadable.title);
int count = Math.max(0, item.watchNewCount - item.watchLastCount);
String total = Integer.toString(Math.min(count, 999));
((TextView) view.findViewById(R.id.drawer_item_count)).setText(total);
FrameLayout frameLayout = (FrameLayout) view.findViewById(R.id.drawer_item_count_container);
// if (Math.random() < 0.5d) {
frameLayout.setBackgroundResource(R.drawable.pin_icon_blue);
// } else {
// frameLayout.setBackgroundResource(R.drawable.pin_icon_red);
// }
}
if (listener != null) {

@ -16,7 +16,7 @@ import com.j256.ormlite.table.TableUtils;
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "ChanDB";
private static final int DATABASE_VERSION = 1;
private static final int DATABASE_VERSION = 3;
public Dao<Pin, Integer> pinDao;
public Dao<Loadable, Integer> loadableDao;
@ -48,6 +48,16 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
switch(oldVersion) {
// Change tables if we make adjustments
}
// Drop the tables and recreate them for now
try {
TableUtils.dropTable(connectionSource, Pin.class, true);
TableUtils.dropTable(connectionSource, Loadable.class, true);
onCreate(database, connectionSource);
} catch (SQLException e) {
e.printStackTrace();
}
}
}

@ -81,6 +81,7 @@ public class ThreadFragment extends Fragment implements ThreadListener {
stopLoading();
this.loadable = loadable;
threadManager.startLoading(loadable);
}

@ -1,5 +1,6 @@
package org.floens.chan.manager;
import java.util.ArrayList;
import java.util.List;
import org.floens.chan.adapter.PinnedAdapter;
@ -13,6 +14,7 @@ public class PinnedManager {
private static PinnedManager instance;
private final Context context;
private final List<PinListener> listeners = new ArrayList<PinListener>();
private final List<Pin> pins;
public PinnedManager(Context context) {
@ -26,6 +28,14 @@ public class PinnedManager {
return instance;
}
public void addPinListener(PinListener l) {
listeners.add(l);
}
public void removePinListener(PinListener l) {
listeners.remove(l);
}
public PinnedAdapter getAdapter() {
PinnedAdapter adapter = new PinnedAdapter(context, 0);
@ -72,6 +82,9 @@ public class PinnedManager {
pins.add(pin);
DatabaseManager.getInstance().addPin(pin);
onPinsChanged();
return true;
}
@ -82,6 +95,8 @@ public class PinnedManager {
public void remove(Pin pin) {
pins.remove(pin);
DatabaseManager.getInstance().removePin(pin);
onPinsChanged();
}
/**
@ -90,6 +105,8 @@ public class PinnedManager {
*/
public void update(Pin pin) {
DatabaseManager.getInstance().updatePin(pin);
onPinsChanged();
}
/**
@ -105,6 +122,22 @@ public class PinnedManager {
}
}).start();
}
public void onPinViewed(Pin pin) {
pin.watchLastCount = pin.watchNewCount;
onPinsChanged();
}
public void onPinsChanged() {
for (PinListener l : listeners) {
l.onPinsChanged();
}
}
public static interface PinListener {
public void onPinsChanged();
}
}

@ -8,6 +8,7 @@ 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.Pin;
import org.floens.chan.model.Post;
import org.floens.chan.model.PostLinkable;
import org.floens.chan.net.ThreadLoader;
@ -35,9 +36,10 @@ import com.android.volley.VolleyError;
/**
* All PostView's need to have this referenced.
* This manages some things like pages, starting and stopping of loading etc.
* This manages some things like pages, starting and stopping of loading,
* handling linkables, replies popups etc.
*/
public class ThreadManager {
public class ThreadManager implements ThreadLoader.ThreadLoaderListener {
private final Activity activity;
private final ThreadLoader threadLoader;
private final ThreadManager.ThreadListener threadListener;
@ -51,17 +53,17 @@ public class ThreadManager {
this.activity = context;
threadListener = listener;
threadLoader = new ThreadLoader(new ThreadLoader.ThreadLoaderListener() {
@Override
public void onError(VolleyError error) {
listener.onThreadLoadError(error);
}
@Override
public void onData(List<Post> result) {
listener.onThreadLoaded(result);
}
});
threadLoader = new ThreadLoader(this);
}
@Override
public void onError(VolleyError error) {
threadListener.onThreadLoadError(error);
}
@Override
public void onData(List<Post> result) {
threadListener.onThreadLoaded(result);
}
public boolean hasThread() {
@ -80,6 +82,11 @@ public class ThreadManager {
this.loadable = loadable;
threadLoader.start(loadable);
Pin pin = PinnedManager.getInstance().findPinByLoadable(loadable);
if (pin != null) {
PinnedManager.getInstance().onPinViewed(pin);
}
}
public void stop() {

@ -32,6 +32,12 @@ public class Loadable {
@DatabaseField
public int listViewTop;
/**
* When simple mode is enabled, CPU intensive methods won't get called.
* This is used for the thread watcher.
*/
public boolean simpleMode = false;
/**
* Constructs an empty loadable.
* The mode is INVALID.
@ -120,6 +126,19 @@ public class Loadable {
bundle.putInt(p + ".listViewTop", listViewTop);
}
public Loadable copy() {
Loadable copy = new Loadable();
copy.mode = mode;
copy.board = board;
copy.no = no;
copy.title = title;
copy.listViewIndex = listViewIndex;
copy.listViewTop = listViewTop;
copy.simpleMode = simpleMode;
return copy;
}
public static class Mode {
public static final int INVALID = -1;
public static final int THREAD = 0;

@ -1,16 +1,12 @@
package org.floens.chan.model;
import java.util.List;
import org.floens.chan.watch.PinWatcher;
import org.floens.chan.net.ThreadLoader;
import org.floens.chan.utils.Logger;
import com.android.volley.VolleyError;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@DatabaseTable
public class Pin implements ThreadLoader.ThreadLoaderListener {
public class Pin {
// Database stuff
@DatabaseField(generatedId = true)
private int id;
@ -27,35 +23,22 @@ public class Pin implements ThreadLoader.ThreadLoaderListener {
};
// PinnedService stuff
public ThreadLoader threadLoader;
public int lastPostCount;
public int newPostCount;
public PinWatcher pinWatcher;
public void update() {
Logger.test("Update in pin");
if (threadLoader == null) {
threadLoader = new ThreadLoader(this);
}
threadLoader.start(loadable);
}
@DatabaseField
public int watchLastCount;
@Override
public void onError(VolleyError error) {
Logger.test("OnError in pin: ", error);
}
@DatabaseField
public int watchNewCount;
@Override
public void onData(List<Post> result) {
Logger.test("OnData in pin: ");
Logger.test("Size: " + result.size());
public void updateWatch() {
if (pinWatcher == null) {
pinWatcher = new PinWatcher(this);
}
newPostCount = result.size();
pinWatcher.update();
}
}

@ -86,7 +86,7 @@ public class Post {
* Finish up the data
* @return false if this data is invalid
*/
public boolean finish() {
public boolean finish(Loadable loadable) {
if (board == null) return false;
if (no < 0 || resto < 0 || date == null) return false;
@ -105,7 +105,7 @@ public class Post {
}
if (rawComment != null) {
comment = parseComment(rawComment);
comment = parseComment(rawComment, loadable.simpleMode);
}
try {
@ -123,9 +123,13 @@ public class Post {
return true;
}
private CharSequence parseComment(String commentRaw) {
CharSequence total = new SpannableString("");
private CharSequence parseComment(String commentRaw, boolean simpleMode) {
if (simpleMode) {
return "";
}
CharSequence total = new SpannableString("");
try {
String comment = commentRaw.replace("<wbr>", "");

@ -2,6 +2,7 @@ package org.floens.chan.net;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.floens.chan.model.Loadable;
import org.floens.chan.model.Post;
@ -13,10 +14,10 @@ import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.extra.JsonReaderRequest;
public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
public class ChanReaderRequest extends JsonReaderRequest<List<Post>> {
private Loadable loadable;
private ChanReaderRequest(String url, Listener<ArrayList<Post>> listener, ErrorListener errorListener) {
private ChanReaderRequest(String url, Listener<List<Post>> listener, ErrorListener errorListener) {
super(url, listener, errorListener);
}
@ -29,7 +30,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
* @param errorListener
* @return New instance of ChanReaderRequest
*/
public static ChanReaderRequest newInstance(Loadable loadable, Listener<ArrayList<Post>> listener, ErrorListener errorListener) {
public static ChanReaderRequest newInstance(Loadable loadable, Listener<List<Post>> listener, ErrorListener errorListener) {
String url;
if (loadable.isBoardMode()) {
@ -54,19 +55,35 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
}
@Override
public ArrayList<Post> readJson(JsonReader reader) {
public List<Post> readJson(JsonReader reader) {
List<Post> list = new ArrayList<Post>();
if (loadable.isBoardMode()) {
return loadBoard(reader);
list = loadBoard(reader);
} else if (loadable.isThreadMode()) {
return loadThread(reader);
list = loadThread(reader);
} else if (loadable.isCatalogMode()) {
return loadCatalog(reader);
list = loadCatalog(reader);
} else {
throw new IllegalArgumentException("Unknown mode");
}
processPosts(list);
return list;
}
private void processPosts(List<Post> posts) {
for (Post post : posts) {
for (Post other : posts) {
if (other.repliesTo.contains(post.no)) {
post.repliesFrom.add(other.no);
}
}
}
}
private ArrayList<Post> loadThread(JsonReader reader) {
private List<Post> loadThread(JsonReader reader) {
ArrayList<Post> list = new ArrayList<Post>();
try {
@ -78,7 +95,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
// Thread array
while (reader.hasNext()) {
// Thread object
list.add(readPostObject(reader, loadable.board));
list.add(readPostObject(reader));
}
reader.endArray();
} else {
@ -100,7 +117,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
return list;
}
private ArrayList<Post> loadBoard(JsonReader reader) {
private List<Post> loadBoard(JsonReader reader) {
ArrayList<Post> list = new ArrayList<Post>();
try {
@ -115,7 +132,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
if (reader.nextName().equals("posts")) {
reader.beginArray();
list.add(readPostObject(reader, loadable.board));
list.add(readPostObject(reader));
// Only consume one post
while (reader.hasNext()) reader.skipValue();
@ -148,7 +165,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
return list;
}
private ArrayList<Post> loadCatalog(JsonReader reader) {
private List<Post> loadCatalog(JsonReader reader) {
ArrayList<Post> list = new ArrayList<Post>();
try {
@ -162,7 +179,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
reader.beginArray(); // Threads array
while (reader.hasNext()) {
list.add(readPostObject(reader, loadable.board));
list.add(readPostObject(reader));
}
reader.endArray();
@ -189,9 +206,9 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
return list;
}
private Post readPostObject(JsonReader reader, String board) throws IllegalStateException, NumberFormatException, IOException {
private Post readPostObject(JsonReader reader) throws IllegalStateException, NumberFormatException, IOException {
Post post = new Post();
post.board = board;
post.board = loadable.board;
reader.beginObject();
while(reader.hasNext()) {
@ -252,7 +269,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ArrayList<Post>> {
}
reader.endObject();
if (!post.finish()) {
if (!post.finish(loadable)) {
throw new IOException("Incorrect data about post received.");
}

@ -1,6 +1,5 @@
package org.floens.chan.net;
import java.util.ArrayList;
import java.util.List;
import org.floens.chan.ChanApplication;
@ -65,9 +64,9 @@ public class ThreadLoader {
}
private ChanReaderRequest getData(Loadable loadable) {
ChanReaderRequest request = ChanReaderRequest.newInstance(loadable, new Response.Listener<ArrayList<Post>>() {
ChanReaderRequest request = ChanReaderRequest.newInstance(loadable, new Response.Listener<List<Post>>() {
@Override
public void onResponse(ArrayList<Post> list) {
public void onResponse(List<Post> list) {
loading = false;
onData(list);
}
@ -88,7 +87,9 @@ public class ThreadLoader {
private void onData(List<Post> result) {
if (stopped) return;
processPosts(result);
for (Post post : result) {
postsById.append(post.no, post);
}
listener.onData(result);
}
@ -106,18 +107,6 @@ 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 interface ThreadLoaderListener {
public abstract void onData(List<Post> result);
public abstract void onError(VolleyError error);

@ -10,7 +10,9 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
public class PinnedService extends Service {
private Thread loadThread;
@ -61,10 +63,20 @@ public class PinnedService extends Service {
private void doUpdates() {
List<Pin> pins = PinnedManager.getInstance().getPins();
for (Pin pin : pins) {
// pin.update();
pin.updateWatch();
// pin.newPostCount++;
}
}
public static void callOnPinsChanged() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
PinnedManager.getInstance().onPinsChanged();
}
});
}
@SuppressWarnings("deprecation")
private void showNotification(String text) {
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

@ -0,0 +1,61 @@
package org.floens.chan.watch;
import java.util.List;
import org.floens.chan.model.Loadable;
import org.floens.chan.model.Pin;
import org.floens.chan.model.Post;
import org.floens.chan.net.ThreadLoader;
import org.floens.chan.service.PinnedService;
import org.floens.chan.utils.Logger;
import com.android.volley.VolleyError;
public class PinWatcher implements ThreadLoader.ThreadLoaderListener {
private static final int[] timeouts = {10, 15, 20, 30, 60, 90, 120, 180, 240, 300};
private final ThreadLoader watchLoader;
private final Loadable watchLoadable;
private final Pin pin;
private long startTime;
public PinWatcher(Pin pin) {
this.pin = pin;
watchLoadable = pin.loadable.copy();
watchLoadable.simpleMode = true;
watchLoader = new ThreadLoader(this);
}
public void update() {
Logger.test("PinWatcher update");
startTime = System.currentTimeMillis();
watchLoader.start(watchLoadable);
}
@Override
public void onError(VolleyError error) {
Logger.test("PinWatcher onError: ", error);
}
@Override
public void onData(List<Post> result) {
int count = result.size();
Logger.i("PinWatcher onData");
Logger.i("Post size: " + count);
pin.watchNewCount = count;
Logger.i("Load time: " + (System.currentTimeMillis() - startTime) + "ms");
PinnedService.callOnPinsChanged();
}
}
Loading…
Cancel
Save