diff --git a/clients/android/NewsBlur/res/menu/main.xml b/clients/android/NewsBlur/res/menu/main.xml
index 5d56c1687..b806f4dc6 100644
--- a/clients/android/NewsBlur/res/menu/main.xml
+++ b/clients/android/NewsBlur/res/menu/main.xml
@@ -18,6 +18,10 @@
+
+
- Search
Mark all as read
Log out
+ Send app feedback
Loading…
No stories to read
diff --git a/clients/android/NewsBlur/src/com/newsblur/activity/ItemsList.java b/clients/android/NewsBlur/src/com/newsblur/activity/ItemsList.java
index 1c173e680..e900a02f8 100644
--- a/clients/android/NewsBlur/src/com/newsblur/activity/ItemsList.java
+++ b/clients/android/NewsBlur/src/com/newsblur/activity/ItemsList.java
@@ -179,7 +179,7 @@ public abstract class ItemsList extends NbActivity implements StateChangedListen
@Override
public void storyOrderChanged(StoryOrder newValue) {
updateStoryOrderPreference(newValue);
- NBSyncService.resetFeed(fs);
+ FeedUtils.clearReadingSession(this);
itemListFragment.resetEmptyState();
itemListFragment.hasUpdated();
itemListFragment.scrollToTop();
@@ -191,7 +191,7 @@ public abstract class ItemsList extends NbActivity implements StateChangedListen
@Override
public void readFilterChanged(ReadFilter newValue) {
updateReadFilterPreference(newValue);
- NBSyncService.resetFeed(fs);
+ FeedUtils.clearReadingSession(this);
itemListFragment.resetEmptyState();
itemListFragment.hasUpdated();
itemListFragment.scrollToTop();
diff --git a/clients/android/NewsBlur/src/com/newsblur/activity/Main.java b/clients/android/NewsBlur/src/com/newsblur/activity/Main.java
index 2e6d25d25..d4139641f 100644
--- a/clients/android/NewsBlur/src/com/newsblur/activity/Main.java
+++ b/clients/android/NewsBlur/src/com/newsblur/activity/Main.java
@@ -6,7 +6,9 @@ import android.os.Bundle;
import android.preference.PreferenceManager;
import android.app.DialogFragment;
import android.app.FragmentManager;
+import android.net.Uri;
import android.support.v4.widget.SwipeRefreshLayout;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -20,6 +22,7 @@ import com.newsblur.fragment.FolderListFragment;
import com.newsblur.fragment.LogoutDialogFragment;
import com.newsblur.service.BootReceiver;
import com.newsblur.service.NBSyncService;
+import com.newsblur.util.AppConstants;
import com.newsblur.util.FeedUtils;
import com.newsblur.util.PrefsUtils;
import com.newsblur.util.UIUtils;
@@ -30,7 +33,6 @@ public class Main extends NbActivity implements StateChangedListener, SwipeRefre
private ActionBar actionBar;
private FolderListFragment folderFeedList;
private FragmentManager fragmentManager;
- private Menu menu;
private TextView overlayStatusText;
private boolean isLightTheme;
private SwipeRefreshLayout swipeLayout;
@@ -91,7 +93,14 @@ public class Main extends NbActivity implements StateChangedListener, SwipeRefre
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
- this.menu = menu;
+
+ MenuItem feedbackItem = menu.findItem(R.id.menu_feedback);
+ if (AppConstants.ENABLE_FEEDBACK) {
+ feedbackItem.setTitle(feedbackItem.getTitle() + " (v" + PrefsUtils.getVersion(this) + ")");
+ } else {
+ feedbackItem.setVisible(false);
+ }
+
return true;
}
@@ -116,6 +125,15 @@ public class Main extends NbActivity implements StateChangedListener, SwipeRefre
Intent settingsIntent = new Intent(this, Settings.class);
startActivity(settingsIntent);
return true;
+ } else if (item.getItemId() == R.id.menu_feedback) {
+ try {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ i.setData(Uri.parse(PrefsUtils.createFeedbackLink(this)));
+ startActivity(i);
+ } catch (Exception e) {
+ Log.wtf(this.getClass().getName(), "device cannot even open URLs to report feedback");
+ }
+ return true;
}
return super.onOptionsItemSelected(item);
}
diff --git a/clients/android/NewsBlur/src/com/newsblur/database/BlurDatabaseHelper.java b/clients/android/NewsBlur/src/com/newsblur/database/BlurDatabaseHelper.java
index b3436aef0..5e4d07111 100644
--- a/clients/android/NewsBlur/src/com/newsblur/database/BlurDatabaseHelper.java
+++ b/clients/android/NewsBlur/src/com/newsblur/database/BlurDatabaseHelper.java
@@ -292,16 +292,16 @@ public class BlurDatabaseHelper {
}
public void markFeedsRead(FeedSet fs, Long olderThan, Long newerThan) {
- // TODO: impl at least the older/newer than cases
+ // split this into two steps, since the double-check feature needs to
+ // redo the second step separately
+ markFeedsRead_feedCounts(fs, olderThan, newerThan);
+ markFeedsRead_storyCounts(fs, olderThan, newerThan);
+ }
- // TODO: stories
-
- // feed counts
+ public void markFeedsRead_feedCounts(FeedSet fs, Long olderThan, Long newerThan) {
if (fs.isAllNormal()) {
setFeedUnreadCount(0, null, null);
- } else if (fs.isAllSocial()) {
- // TODO: oddly, the client never supported this before, so there is no button to invoke it. The API call
- // works, though, so adding an impl. here should let us enable the button.
+ setSocialFeedUnreadCount(0, null, null);
} else if (fs.getMultipleFeeds() != null) {
for (String feedId : fs.getMultipleFeeds()) {
setFeedUnreadCount(0, DatabaseConstants.FEED_ID + " = ?", new String[]{feedId});
@@ -311,10 +311,38 @@ public class BlurDatabaseHelper {
} else if (fs.getSingleSocialFeed() != null) {
setSocialFeedUnreadCount(0, DatabaseConstants.SOCIAL_FEED_ID + " = ?", new String[]{fs.getSingleSocialFeed().getKey()});
} else {
- throw new IllegalStateException("Asked to get stories for FeedSet of unknown type.");
+ // TODO: fs.isAllSocial() was never supported by the UI, but the API has it, and it would be
+ // easy enough to add here. Should we?
+ throw new IllegalStateException("Asked to mark stories for FeedSet of unknown type.");
}
}
+ public void markFeedsRead_storyCounts(FeedSet fs, Long olderThan, Long newerThan) {
+ ContentValues values = new ContentValues();
+ values.put(DatabaseConstants.STORY_READ, true);
+ String rangeSelection = null;
+ if (olderThan != null) rangeSelection = DatabaseConstants.STORY_TIMESTAMP + " <= " + olderThan.toString();
+ if (newerThan != null) rangeSelection = DatabaseConstants.STORY_TIMESTAMP + " >= " + newerThan.toString();
+ StringBuilder feedSelection = null;
+ if (fs.isAllNormal()) {
+ // a null selection is fine for all stories
+ } else if (fs.getMultipleFeeds() != null) {
+ feedSelection = new StringBuilder(DatabaseConstants.STORY_FEED_ID + " IN ( ");
+ feedSelection.append(TextUtils.join(",", fs.getMultipleFeeds()));
+ feedSelection.append(")");
+ } else if (fs.getSingleFeed() != null) {
+ feedSelection= new StringBuilder(DatabaseConstants.STORY_FEED_ID + " = ");
+ feedSelection.append(fs.getSingleFeed());
+ } else if (fs.getSingleSocialFeed() != null) {
+ feedSelection= new StringBuilder(DatabaseConstants.STORY_SOCIAL_USER_ID + " = ");
+ feedSelection.append(fs.getSingleSocialFeed().getKey());
+ } else {
+ throw new IllegalStateException("Asked to mark stories for FeedSet of unknown type.");
+ }
+ dbRW.update(DatabaseConstants.STORY_TABLE, values, conjoinSelections(feedSelection, rangeSelection), null);
+
+ }
+
private void setFeedUnreadCount(int count, String whereClause, String[] whereArgs) {
ContentValues values = new ContentValues();
values.put(DatabaseConstants.FEED_NEGATIVE_COUNT, count);
@@ -485,4 +513,19 @@ public class BlurDatabaseHelper {
try {c.close();} catch (Exception e) {;}
}
+ private static String conjoinSelections(CharSequence... args) {
+ StringBuilder s = null;
+ for (CharSequence c : args) {
+ if (c == null) continue;
+ if (s == null) {
+ s = new StringBuilder(c);
+ } else {
+ s.append(" AND ");
+ s.append(c);
+ }
+ }
+ if (s == null) return null;
+ return s.toString();
+ }
+
}
diff --git a/clients/android/NewsBlur/src/com/newsblur/database/DatabaseConstants.java b/clients/android/NewsBlur/src/com/newsblur/database/DatabaseConstants.java
index 5080361b2..faf801534 100644
--- a/clients/android/NewsBlur/src/com/newsblur/database/DatabaseConstants.java
+++ b/clients/android/NewsBlur/src/com/newsblur/database/DatabaseConstants.java
@@ -468,4 +468,10 @@ public class DatabaseConstants {
}
}
+ public static Long nullIfZero(Long l) {
+ if (l == null) return null;
+ if (l.longValue() == 0L) return null;
+ return l;
+ }
+
}
diff --git a/clients/android/NewsBlur/src/com/newsblur/database/FeedProvider.java b/clients/android/NewsBlur/src/com/newsblur/database/FeedProvider.java
index 92aac2de9..5ece211a6 100644
--- a/clients/android/NewsBlur/src/com/newsblur/database/FeedProvider.java
+++ b/clients/android/NewsBlur/src/com/newsblur/database/FeedProvider.java
@@ -309,24 +309,24 @@ public class FeedProvider extends ContentProvider {
mdb = db;
}
public Cursor rawQuery(String sql, String[] selectionArgs) {
- if (AppConstants.VERBOSE_LOG) {
+ if (AppConstants.VERBOSE_LOG_DB) {
Log.d(LoggingDatabase.class.getName(), "rawQuery: " + sql);
Log.d(LoggingDatabase.class.getName(), "selArgs : " + Arrays.toString(selectionArgs));
}
Cursor cursor = mdb.rawQuery(sql, selectionArgs);
- if (AppConstants.VERBOSE_LOG) {
+ if (AppConstants.VERBOSE_LOG_DB) {
Log.d(LoggingDatabase.class.getName(), "result rows: " + cursor.getCount());
}
return cursor;
}
public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) {
- if (AppConstants.VERBOSE_LOG) {
+ if (AppConstants.VERBOSE_LOG_DB) {
Log.d(LoggingDatabase.class.getName(), "selection: " + selection);
}
return mdb.query(table, columns, selection, selectionArgs, groupBy, having, orderBy);
}
public void execSQL(String sql) {
- if (AppConstants.VERBOSE_LOG) {
+ if (AppConstants.VERBOSE_LOG_DB) {
Log.d(LoggingDatabase.class.getName(), "execSQL: " + sql);
}
mdb.execSQL(sql);
diff --git a/clients/android/NewsBlur/src/com/newsblur/network/APIConstants.java b/clients/android/NewsBlur/src/com/newsblur/network/APIConstants.java
index 04bed9c98..7f0258bdc 100644
--- a/clients/android/NewsBlur/src/com/newsblur/network/APIConstants.java
+++ b/clients/android/NewsBlur/src/com/newsblur/network/APIConstants.java
@@ -68,12 +68,15 @@ public class APIConstants {
public static final String PARAMETER_URL = "url";
public static final String PARAMETER_DAYS = "days";
public static final String PARAMETER_UPDATE_COUNTS = "update_counts";
-
+ public static final String PARAMETER_CUTOFF_TIME = "cutoff_timestamp";
+ public static final String PARAMETER_DIRECTION = "direction";
public static final String PARAMETER_PAGE_NUMBER = "page";
public static final String PARAMETER_ORDER = "order";
public static final String PARAMETER_READ_FILTER = "read_filter";
public static final String VALUE_ALLSOCIAL = "river:blurblogs"; // the magic value passed to the mark-read API for all social feeds
+ public static final String VALUE_OLDER = "older";
+ public static final String VALUE_NEWER = "newer";
public static final String URL_CONNECT_FACEBOOK = NEWSBLUR_URL + "/oauth/facebook_connect/";
public static final String URL_CONNECT_TWITTER = NEWSBLUR_URL + "/oauth/twitter_connect/";
diff --git a/clients/android/NewsBlur/src/com/newsblur/network/APIManager.java b/clients/android/NewsBlur/src/com/newsblur/network/APIManager.java
index 22e4c175b..67f8e09ba 100644
--- a/clients/android/NewsBlur/src/com/newsblur/network/APIManager.java
+++ b/clients/android/NewsBlur/src/com/newsblur/network/APIManager.java
@@ -122,7 +122,18 @@ public class APIManager {
for (String feedId : feedIds) {
values.put(APIConstants.PARAMETER_FEEDID, feedId);
}
- // TODO: handle older/newer
+ if (includeOlder != null) {
+ // the app uses milliseconds but the API wants seconds
+ long cut = includeOlder.longValue();
+ values.put(APIConstants.PARAMETER_CUTOFF_TIME, Long.toString(cut/1000L));
+ values.put(APIConstants.PARAMETER_DIRECTION, APIConstants.VALUE_OLDER);
+ }
+ if (includeNewer != null) {
+ // the app uses milliseconds but the API wants seconds
+ long cut = includeNewer.longValue();
+ values.put(APIConstants.PARAMETER_CUTOFF_TIME, Long.toString(cut/1000L));
+ values.put(APIConstants.PARAMETER_DIRECTION, APIConstants.VALUE_NEWER);
+ }
APIResponse response = post(APIConstants.URL_MARK_FEED_AS_READ, values, false);
// TODO: these calls use a different return format than others: the errors field is an array, not an object
diff --git a/clients/android/NewsBlur/src/com/newsblur/service/NBSyncService.java b/clients/android/NewsBlur/src/com/newsblur/service/NBSyncService.java
index 8bfe6a548..cef29f092 100644
--- a/clients/android/NewsBlur/src/com/newsblur/service/NBSyncService.java
+++ b/clients/android/NewsBlur/src/com/newsblur/service/NBSyncService.java
@@ -69,6 +69,11 @@ public class NBSyncService extends Service {
would annoy a user who is on the story list or paging through stories. */
private volatile static boolean HoldStories = false;
private volatile static boolean DoFeedsFolders = false;
+ private volatile static boolean isMemoryLow = false;
+ private volatile static boolean HaltNow = false;
+
+ private static long lastFeedCount = 0L;
+ private static long lastFFWriteMillis = 0L;
/** Feed sets that we need to sync and how many stories the UI wants for them. */
private static Map PendingFeeds;
@@ -84,8 +89,6 @@ public class NBSyncService extends Service {
private static Set ImageQueue;
static { ImageQueue = new HashSet(); }
- private volatile static boolean HaltNow;
-
private PowerManager.WakeLock wl = null;
private ExecutorService executor;
private APIManager apiManager;
@@ -138,7 +141,12 @@ public class NBSyncService extends Service {
*/
private synchronized void doSync(int startId) {
try {
- if (HaltNow) return;
+ if (HaltNow) {
+ if (AppConstants.VERBOSE_LOG) {
+ Log.d(this.getClass().getName(), "skipping sync, soft interrupt set.");
+ }
+ return;
+ }
Log.d(this.getClass().getName(), "starting sync . . .");
@@ -171,6 +179,10 @@ public class NBSyncService extends Service {
if (wl != null) wl.release();
Log.d(this.getClass().getName(), " . . . sync done");
}
+
+ if (isMemoryLow && (NbActivity.getActiveActivityCount() < 1)) {
+ stopSelf(startId);
+ }
}
/**
@@ -195,8 +207,8 @@ public class NBSyncService extends Service {
if (c.getInt(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_MARK_READ)) == 1) {
String hash = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_STORY_HASH));
String feedIds = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_FEED_ID));
- Long includeOlder = c.getLong(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_STORY_HASH));
- Long includeNewer = c.getLong(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_STORY_HASH));
+ Long includeOlder = DatabaseConstants.nullIfZero(c.getLong(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_INCLUDE_OLDER)));
+ Long includeNewer = DatabaseConstants.nullIfZero(c.getLong(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_INCLUDE_NEWER)));
if (hash != null) {
response = apiManager.markStoryAsRead(hash);
} else if (feedIds != null) {
@@ -253,7 +265,10 @@ public class NBSyncService extends Service {
String id = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_ID));
if (c.getInt(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_MARK_READ)) == 1) {
String hash = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_STORY_HASH));
- dbHelper.setStoryReadState(hash, true);
+ if (hash != null ) {
+ dbHelper.setStoryReadState(hash, true);
+ }
+ // TODO: double-check stories from feed-marks
} else if (c.getInt(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_MARK_UNREAD)) == 1) {
String hash = c.getString(c.getColumnIndexOrThrow(DatabaseConstants.ACTION_STORY_HASH));
dbHelper.setStoryReadState(hash, false);
@@ -324,6 +339,8 @@ public class NBSyncService extends Service {
return;
}
+ long startTime = System.currentTimeMillis();
+
isPremium = feedResponse.isPremium;
// clean out the feed / folder tables
@@ -375,6 +392,9 @@ public class NBSyncService extends Service {
// populate the starred stories count table
dbHelper.updateStarredStoriesCount(feedResponse.starredCount);
+ lastFFWriteMillis = System.currentTimeMillis() - startTime;
+ lastFeedCount = feedValues.size();
+
} finally {
FFSyncRunning = false;
NbActivity.updateAllActivities();
@@ -561,12 +581,14 @@ public class NBSyncService extends Service {
}
public void onTrimMemory (int level) {
- // if the UI is still active, definitely don't stop
- if (NbActivity.getActiveActivityCount() > 0) return;
-
// be nice and stop if memory is even a tiny bit pressured and we aren't visible;
// the OS penalises long-running processes, and it is reasonably cheap to re-create ourself.
if (level > ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
+ isMemoryLow = true;
+
+ // if the UI is still active, definitely don't stop
+ if (NbActivity.getActiveActivityCount() > 0) return;
+
if (lastStartIdCompleted != -1) {
stopSelf(lastStartIdCompleted);
}
@@ -642,14 +664,10 @@ public class NBSyncService extends Service {
return true;
}
- /**
- * Resets pagination and exhaustion flags for the given feedset, so that it can be requested fresh
- * from the beginning with new parameters.
- */
- public static void resetFeed(FeedSet fs) {
- ExhaustedFeeds.remove(fs);
- FeedPagesSeen.put(fs, 0);
- FeedStoriesSeen.put(fs, 0);
+ public static void resetFeeds() {
+ ExhaustedFeeds.clear();
+ FeedPagesSeen.clear();
+ FeedStoriesSeen.clear();
}
public static void softInterrupt() {
@@ -657,6 +675,10 @@ public class NBSyncService extends Service {
HaltNow = true;
}
+ public static void resumeFromInterrupt() {
+ HaltNow = false;
+ }
+
@Override
public void onDestroy() {
Log.d(this.getClass().getName(), "onDestroy");
@@ -671,4 +693,14 @@ public class NBSyncService extends Service {
return null;
}
+ public static boolean isMemoryLow() {
+ return isMemoryLow;
+ }
+
+ public static String getSpeedInfo() {
+ StringBuilder s = new StringBuilder();
+ s.append(lastFeedCount).append(" in ").append(lastFFWriteMillis);
+ return s.toString();
+ }
+
}
diff --git a/clients/android/NewsBlur/src/com/newsblur/util/AppConstants.java b/clients/android/NewsBlur/src/com/newsblur/util/AppConstants.java
index 5fcd746d4..e755a2f20 100644
--- a/clients/android/NewsBlur/src/com/newsblur/util/AppConstants.java
+++ b/clients/android/NewsBlur/src/com/newsblur/util/AppConstants.java
@@ -5,7 +5,8 @@ public class AppConstants {
// Enables high-volume logging that may be useful for debugging. This should
// never be enabled for releases, as it not only slows down the app considerably,
// it will log sensitive info such as passwords!
- public static final boolean VERBOSE_LOG = false;
+ public static final boolean VERBOSE_LOG = true;
+ public static final boolean VERBOSE_LOG_DB = false;
public static final int STATE_ALL = 0;
public static final int STATE_SOME = 1;
@@ -58,4 +59,10 @@ public class AppConstants {
// how many images to prefetch before updating the countdown UI
public static final int IMAGE_PREFETCH_BATCH_SIZE = 10;
+ // should the feedback link be enabled (read: is this a beta?)
+ public static final boolean ENABLE_FEEDBACK = true;
+
+ // link to app feedback page
+ public static final String FEEDBACK_URL = "https://getsatisfaction.com/newsblur/topics/new?topic[style]=question&from=company&product=NewsBlur+Android+App&topic[additional_detail]=";
+
}
diff --git a/clients/android/NewsBlur/src/com/newsblur/util/FeedUtils.java b/clients/android/NewsBlur/src/com/newsblur/util/FeedUtils.java
index 3690c9fb9..f6a341782 100644
--- a/clients/android/NewsBlur/src/com/newsblur/util/FeedUtils.java
+++ b/clients/android/NewsBlur/src/com/newsblur/util/FeedUtils.java
@@ -117,6 +117,7 @@ public class FeedUtils {
} catch (Exception e) {
; // this one call can evade the on-upgrade DB wipe and throw exceptions
}
+ NBSyncService.resetFeeds();
return null;
}
}.execute();
diff --git a/clients/android/NewsBlur/src/com/newsblur/util/PrefsUtils.java b/clients/android/NewsBlur/src/com/newsblur/util/PrefsUtils.java
index 4f9214eda..686542363 100644
--- a/clients/android/NewsBlur/src/com/newsblur/util/PrefsUtils.java
+++ b/clients/android/NewsBlur/src/com/newsblur/util/PrefsUtils.java
@@ -19,6 +19,7 @@ import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
+import android.os.Build;
import android.util.Log;
import com.newsblur.R;
@@ -30,6 +31,7 @@ import com.newsblur.service.NBSyncService;
public class PrefsUtils {
public static void saveLogin(final Context context, final String userName, final String cookie) {
+ NBSyncService.resumeFromInterrupt();
final SharedPreferences preferences = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
final Editor edit = preferences.edit();
edit.putString(PrefConstants.PREF_COOKIE, cookie);
@@ -45,10 +47,8 @@ public class PrefsUtils {
SharedPreferences prefs = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
- String version;
- try {
- version = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
- } catch (NameNotFoundException nnfe) {
+ String version = getVersion(context);
+ if (version == null) {
Log.w(PrefsUtils.class.getName(), "could not determine app version");
return;
}
@@ -72,6 +72,26 @@ public class PrefsUtils {
}
+ public static String getVersion(Context context) {
+ try {
+ return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
+ } catch (NameNotFoundException nnfe) {
+ Log.w(PrefsUtils.class.getName(), "could not determine app version");
+ return null;
+ }
+ }
+
+ public static String createFeedbackLink(Context context) {
+ StringBuilder s = new StringBuilder(AppConstants.FEEDBACK_URL);
+ s.append("%0A%0A");
+ s.append("%0Aapp version: ").append(getVersion(context));
+ s.append("%0Aandroid version: ").append(Build.VERSION.RELEASE);
+ s.append("%0Adevice: ").append(Build.MANUFACTURER + "+" + Build.MODEL + "+(" + Build.BOARD + ")");
+ s.append("%0Amemory: ").append(NBSyncService.isMemoryLow() ? "low" : "normal");
+ s.append("%0Aspeed: ").append(NBSyncService.getSpeedInfo());
+ return s.toString();
+ }
+
public static void logout(Context context) {
NBSyncService.softInterrupt();
diff --git a/clients/android/NewsBlur/src/com/newsblur/view/SocialItemViewBinder.java b/clients/android/NewsBlur/src/com/newsblur/view/SocialItemViewBinder.java
index 12cc89054..6699772c9 100644
--- a/clients/android/NewsBlur/src/com/newsblur/view/SocialItemViewBinder.java
+++ b/clients/android/NewsBlur/src/com/newsblur/view/SocialItemViewBinder.java
@@ -70,9 +70,12 @@ public class SocialItemViewBinder implements ViewBinder {
return true;
} else if (TextUtils.equals(columnName, DatabaseConstants.STORY_AUTHORS)) {
String authors = cursor.getString(columnIndex);
- if (!TextUtils.isEmpty(authors)) {
- ((TextView) view).setText(authors.toUpperCase());
- }
+ if (TextUtils.isEmpty(authors)) {
+ view.setVisibility(View.GONE);
+ } else {
+ ((TextView) view).setText(authors.toUpperCase());
+ view.setVisibility(View.VISIBLE);
+ }
return true;
} else if (TextUtils.equals(columnName, DatabaseConstants.STORY_TITLE)) {
((TextView) view).setText(Html.fromHtml(cursor.getString(columnIndex)));