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. 113
      Chan/src/org/floens/chan/ui/activity/BaseActivity.java
  6. 2
      Chan/src/org/floens/chan/ui/adapter/PinnedAdapter.java

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

@ -75,7 +75,7 @@ public class WatchNotifier {
for (Pin pin : watchingPins) {
PinWatcher watcher = pin.getPinWatcher();
if (watcher == null || watcher.isError())
if (watcher == null || pin.isError)
continue;
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;
import java.util.List;
import org.floens.chan.ChanApplication;
import org.floens.chan.R;
import org.floens.chan.core.manager.PinnedManager;
import org.floens.chan.core.model.Pin;
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.DismissCallbacks;
import org.floens.chan.ui.adapter.PinnedAdapter;
@ -15,6 +18,7 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.nfc.NdefMessage;
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
*
* @param post
*/
abstract public void openPin(Pin post);
/**
* Called when a post has been clicked in the listview
*
* @param post
*/
abstract public void onOPClicked(Post post);
@ -74,6 +80,8 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
initPane();
ChanApplication.getPinnedManager().addPinListener(this);
updateIcon();
}
@Override
@ -87,7 +95,7 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// pinDrawer.openDrawer(pinDrawerView);
// pinDrawer.openDrawer(pinDrawerView);
}
private void initPane() {
@ -106,7 +114,7 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
pinDrawer.setDrawerListener(pinDrawerListener);
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.reload();
@ -116,7 +124,8 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
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);
}
});
@ -125,7 +134,8 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
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);
@ -134,19 +144,19 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
});
SwipeDismissListViewTouchListener touchListener = new SwipeDismissListViewTouchListener(pinDrawerView,
new DismissCallbacks() {
@Override
public void onDismiss(ListView listView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
removePin(pinnedAdapter.getItem(position));
new DismissCallbacks() {
@Override
public void onDismiss(ListView listView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
removePin(pinnedAdapter.getItem(position));
}
}
}
@Override
public boolean canDismiss(int position) {
return pinnedAdapter.getItem(position).type != Pin.Type.HEADER;
}
});
@Override
public boolean canDismiss(int position) {
return pinnedAdapter.getItem(position).type != Pin.Type.HEADER;
}
});
pinDrawerView.setOnTouchListener(touchListener);
pinDrawerView.setOnScrollListener(touchListener.makeScrollListener());
@ -156,6 +166,30 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
public void onPinsChanged() {
pinnedAdapter.reload();
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) {
@ -177,25 +211,21 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
text.setSelectAllOnFocus(true);
AlertDialog dialog = new AlertDialog.Builder(this)
.setPositiveButton(R.string.change, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface d, int which) {
String value = text.getText().toString();
if (!TextUtils.isEmpty(value)) {
pin.loadable.title = value;
updatePin(pin);
.setPositiveButton(R.string.change, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface d, int which) {
String value = text.getText().toString();
if (!TextUtils.isEmpty(value)) {
pin.loadable.title = value;
updatePin(pin);
}
}
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface d, int which) {
}
})
.setTitle(R.string.drawer_pinned_change_title)
.setView(text)
.create();
}).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface d, int which) {
}
}).setTitle(R.string.drawer_pinned_change_title).setView(text).create();
text.requestFocus();
@ -212,7 +242,7 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
switch (item.getItemId()) {
case R.id.action_settings:
startActivity(new Intent(this, SettingsActivity.class));
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.
*
* @param url
*/
public void setShareUrl(String url) {
@ -252,12 +283,12 @@ public abstract class BaseActivity extends Activity implements PanelSlideListene
NdefRecord record = null;
try {
record = NdefRecord.createUri(url);
} catch(IllegalArgumentException e) {
} catch (IllegalArgumentException e) {
e.printStackTrace();
return;
}
NdefMessage message = new NdefMessage(new NdefRecord[] {record});
NdefMessage message = new NdefMessage(new NdefRecord[] { record });
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.
* This is done to prevent "open in browser" opening the url in our own app.
* Let the user choose between all activities that can open the url. This is
* done to prevent "open in browser" opening the url in our own app.
*
* @param 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);
if (item.isError()) {
if (item.isError) {
itemCount.setText("Err");
} else {
int count = item.getNewPostsCount();

Loading…
Cancel
Save