Added a badge on the ActionBar icon for new posts.

Colored gray and red with red as new replies.
Shows the total count of new posts of watching pins.
captchafix
Florens Douwes 11 years ago
parent f47ac33d93
commit 01e12dfbf9
  1. 10
      Chan/src/org/floens/chan/core/model/Pin.java
  2. 11
      Chan/src/org/floens/chan/core/watch/PinWatcher.java
  3. 2
      Chan/src/org/floens/chan/core/watch/WatchNotifier.java
  4. 65
      Chan/src/org/floens/chan/ui/BadgeDrawable.java
  5. 67
      Chan/src/org/floens/chan/ui/activity/BaseActivity.java
  6. 2
      Chan/src/org/floens/chan/ui/adapter/PinnedAdapter.java

@ -40,6 +40,8 @@ public class Pin {
@DatabaseField @DatabaseField
public int quoteNewCount; public int quoteNewCount;
public boolean isError = false;
public PinWatcher getPinWatcher() { public PinWatcher getPinWatcher() {
return pinWatcher; return pinWatcher;
} }
@ -82,14 +84,6 @@ public class Pin {
pinWatcher = null; pinWatcher = null;
} }
} }
public boolean isError() {
if (pinWatcher != null) {
return pinWatcher.isError();
} else {
return false;
}
}
} }

@ -17,7 +17,6 @@ public class PinWatcher implements Loader.LoaderListener {
private final Pin pin; private final Pin pin;
private Loader loader; private Loader loader;
private boolean isError = false;
private final List<Post> posts = new ArrayList<Post>(); private final List<Post> posts = new ArrayList<Post>();
private boolean wereNewQuotes = false; private boolean wereNewQuotes = false;
@ -36,7 +35,7 @@ public class PinWatcher implements Loader.LoaderListener {
} }
public void update() { public void update() {
if (!isError) { if (!pin.isError) {
loader.loadMoreIfTime(); loader.loadMoreIfTime();
} }
} }
@ -80,21 +79,17 @@ public class PinWatcher implements Loader.LoaderListener {
} }
} }
public boolean isError() {
return isError;
}
@Override @Override
public void onError(VolleyError error) { public void onError(VolleyError error) {
Logger.e(TAG, "PinWatcher onError: ", error); Logger.e(TAG, "PinWatcher onError: ", error);
isError = true; pin.isError = true;
WatchService.onPinWatcherResult(); WatchService.onPinWatcherResult();
} }
@Override @Override
public void onData(List<Post> result, boolean append) { public void onData(List<Post> result, boolean append) {
isError = false; pin.isError = false;
posts.clear(); posts.clear();
posts.addAll(result); posts.addAll(result);

@ -75,7 +75,7 @@ public class WatchNotifier {
for (Pin pin : watchingPins) { for (Pin pin : watchingPins) {
PinWatcher watcher = pin.getPinWatcher(); PinWatcher watcher = pin.getPinWatcher();
if (watcher == null || watcher.isError()) if (watcher == null || pin.isError)
continue; continue;
boolean add = false; boolean add = false;

@ -0,0 +1,65 @@
package org.floens.chan.ui;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
public class BadgeDrawable {
public static Drawable get(Resources resources, int id, int count, boolean red) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inMutable = true;
Bitmap bitmap = BitmapFactory.decodeResource(resources, id, opt);
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Paint paint = new Paint();
paint.setAntiAlias(true);
Canvas canvas = new Canvas(bitmap);
float badgeX = w * 0.3f;
float badgeY = h * 0.3f;
float badgeW = w * 0.6f;
float badgeH = h * 0.6f;
RectF rect = new RectF(badgeX, badgeY, badgeX + badgeW, badgeY + badgeH);
if (red) {
paint.setColor(0xffff4444);
} else {
paint.setColor(0xaa000000);
}
canvas.drawRoundRect(rect, w * 0.1f, h * 0.1f, paint);
String text = Integer.toString(count);
if (count > 999) {
text = "1k+";
}
paint.setColor(0xffffffff);
float textHeight;
float bottomOffset;
if (text.length() <= 2) {
textHeight = badgeH * 0.8f;
bottomOffset = badgeH * 0.2f;
} else {
textHeight = badgeH * 0.5f;
bottomOffset = badgeH * 0.3f;
}
paint.setTextSize(textHeight);
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
canvas.drawText(text, badgeX + badgeW / 2f - bounds.right / 2f, badgeY + badgeH - bottomOffset, paint);
return new BitmapDrawable(resources, bitmap);
}
}

@ -1,10 +1,13 @@
package org.floens.chan.ui.activity; package org.floens.chan.ui.activity;
import java.util.List;
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.PinnedManager; import org.floens.chan.core.manager.PinnedManager;
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.ui.BadgeDrawable;
import org.floens.chan.ui.SwipeDismissListViewTouchListener; import org.floens.chan.ui.SwipeDismissListViewTouchListener;
import org.floens.chan.ui.SwipeDismissListViewTouchListener.DismissCallbacks; import org.floens.chan.ui.SwipeDismissListViewTouchListener.DismissCallbacks;
import org.floens.chan.ui.adapter.PinnedAdapter; import org.floens.chan.ui.adapter.PinnedAdapter;
@ -15,6 +18,7 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener; import android.content.DialogInterface.OnShowListener;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.nfc.NdefMessage; import android.nfc.NdefMessage;
import android.nfc.NdefRecord; import android.nfc.NdefRecord;
@ -51,12 +55,14 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
/** /**
* Called when a post has been clicked in the pinned drawer * Called when a post has been clicked in the pinned drawer
*
* @param post * @param post
*/ */
abstract public void openPin(Pin post); abstract public void openPin(Pin post);
/** /**
* Called when a post has been clicked in the listview * Called when a post has been clicked in the listview
*
* @param post * @param post
*/ */
abstract public void onOPClicked(Post post); abstract public void onOPClicked(Post post);
@ -74,6 +80,8 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
initPane(); initPane();
ChanApplication.getPinnedManager().addPinListener(this); ChanApplication.getPinnedManager().addPinListener(this);
updateIcon();
} }
@Override @Override
@ -87,7 +95,7 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
protected void onNewIntent(Intent intent) { protected void onNewIntent(Intent intent) {
super.onNewIntent(intent); super.onNewIntent(intent);
// pinDrawer.openDrawer(pinDrawerView); // pinDrawer.openDrawer(pinDrawerView);
} }
private void initPane() { private void initPane() {
@ -106,7 +114,7 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
pinDrawer.setDrawerListener(pinDrawerListener); pinDrawer.setDrawerListener(pinDrawerListener);
pinDrawer.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); pinDrawer.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
pinDrawerView = (ListView)findViewById(R.id.left_drawer); pinDrawerView = (ListView) findViewById(R.id.left_drawer);
pinnedAdapter = new PinnedAdapter(getActionBar().getThemedContext(), 0); // Get the dark theme, not the light one pinnedAdapter = new PinnedAdapter(getActionBar().getThemedContext(), 0); // Get the dark theme, not the light one
pinnedAdapter.reload(); pinnedAdapter.reload();
@ -116,7 +124,8 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
@Override @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Pin pin = pinnedAdapter.getItem(position); Pin pin = pinnedAdapter.getItem(position);
if (pin == null || pin.type == Pin.Type.HEADER) return; if (pin == null || pin.type == Pin.Type.HEADER)
return;
openPin(pin); openPin(pin);
} }
}); });
@ -125,7 +134,8 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
@Override @Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
Pin post = pinnedAdapter.getItem(position); Pin post = pinnedAdapter.getItem(position);
if (post == null || post.type == Pin.Type.HEADER) return false; if (post == null || post.type == Pin.Type.HEADER)
return false;
changePinTitle(post); changePinTitle(post);
@ -156,6 +166,30 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
public void onPinsChanged() { public void onPinsChanged() {
pinnedAdapter.reload(); pinnedAdapter.reload();
pinDrawerView.invalidate(); pinDrawerView.invalidate();
updateIcon();
}
private void updateIcon() {
List<Pin> list = ChanApplication.getPinnedManager().getWatchingPins();
if (list.size() > 0) {
int count = 0;
boolean color = false;
for (Pin p : list) {
count += p.getNewPostsCount();
if (p.getNewQuoteCount() > 0) {
color = true;
}
}
if (count > 0) {
Drawable icon = BadgeDrawable.get(getResources(), R.drawable.ic_launcher, count, color);
getActionBar().setIcon(icon);
} else {
getActionBar().setIcon(R.drawable.ic_launcher);
}
} else {
getActionBar().setIcon(R.drawable.ic_launcher);
}
} }
public void addPin(Pin pin) { public void addPin(Pin pin) {
@ -187,15 +221,11 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
updatePin(pin); updatePin(pin);
} }
} }
}) }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface d, int which) { public void onClick(DialogInterface d, int which) {
} }
}) }).setTitle(R.string.drawer_pinned_change_title).setView(text).create();
.setTitle(R.string.drawer_pinned_change_title)
.setView(text)
.create();
text.requestFocus(); text.requestFocus();
@ -212,7 +242,7 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) { switch (item.getItemId()) {
case R.id.action_settings: case R.id.action_settings:
startActivity(new Intent(this, SettingsActivity.class)); startActivity(new Intent(this, SettingsActivity.class));
return true; return true;
@ -243,6 +273,7 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
/** /**
* Set the url that Android Beam and the share action will send. * Set the url that Android Beam and the share action will send.
*
* @param url * @param url
*/ */
public void setShareUrl(String url) { public void setShareUrl(String url) {
@ -252,12 +283,12 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
NdefRecord record = null; NdefRecord record = null;
try { try {
record = NdefRecord.createUri(url); record = NdefRecord.createUri(url);
} catch(IllegalArgumentException e) { } catch (IllegalArgumentException e) {
e.printStackTrace(); e.printStackTrace();
return; return;
} }
NdefMessage message = new NdefMessage(new NdefRecord[] {record}); NdefMessage message = new NdefMessage(new NdefRecord[] { record });
adapter.setNdefPushMessage(message, this); adapter.setNdefPushMessage(message, this);
} }
@ -270,8 +301,9 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
} }
/** /**
* Let the user choose between all activities that can open the url. * Let the user choose between all activities that can open the url. This is
* This is done to prevent "open in browser" opening the url in our own app. * done to prevent "open in browser" opening the url in our own app.
*
* @param url * @param url
*/ */
public void showUrlOpenPicker(String url) { public void showUrlOpenPicker(String url) {
@ -296,8 +328,3 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
} }
} }
} }

@ -50,7 +50,7 @@ public class PinnedAdapter extends ArrayAdapter<Pin> {
TextView itemCount = (TextView) view.findViewById(R.id.drawer_item_count); TextView itemCount = (TextView) view.findViewById(R.id.drawer_item_count);
if (item.isError()) { if (item.isError) {
itemCount.setText("Err"); itemCount.setText("Err");
} else { } else {
int count = item.getNewPostsCount(); int count = item.getNewPostsCount();

Loading…
Cancel
Save