Merge remote-tracking branch 'upstream/master' into defaultview

Conflicts:
	clients/android/NewsBlur/src/com/newsblur/fragment/ItemListFragment.java
This commit is contained in:
Mark Anderson 2014-01-13 22:17:33 +00:00
commit 0c4615eb2a
8 changed files with 78 additions and 52 deletions

View file

@ -104,7 +104,7 @@ public abstract class ItemsList extends NbFragmentActivity implements ActionComp
public void actionCompleteCallback(boolean noMoreData) {
if (itemListFragment != null) {
itemListFragment.hasUpdated();
itemListFragment.setEmptyListView(R.string.empty_list_view_no_stories);
itemListFragment.syncDone();;
}
setSupportProgressBarIndeterminateVisibility(false);
if (noMoreData) {

View file

@ -55,7 +55,7 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
public static final String EXTRA_DEFAULT_FEED_VIEW = "default_feed_view";
private static final String TEXT_SIZE = "textsize";
private static final int OVERLAY_RANGE_TOP_DP = 45;
private static final int OVERLAY_RANGE_TOP_DP = 40;
private static final int OVERLAY_RANGE_BOT_DP = 60;
/** The minimum screen width (in DP) needed to show all the overlay controls. */
@ -164,7 +164,6 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
try {
readingAdapter.notifyDataSetChanged();
this.enableOverlays();
checkStoryCount(pager.getCurrentItem());
if (this.unreadSearchLatch != null) {
this.unreadSearchLatch.countDown();
@ -318,13 +317,21 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
}
private void setOverlayAlpha(float a) {
UIUtils.setViewAlpha(this.overlayLeft, a);
UIUtils.setViewAlpha(this.overlayRight, a);
UIUtils.setViewAlpha(this.overlayProgress, a);
UIUtils.setViewAlpha(this.overlayProgressLeft, a);
UIUtils.setViewAlpha(this.overlayProgressRight, a);
UIUtils.setViewAlpha(this.overlayText, a);
UIUtils.setViewAlpha(this.overlaySend, a);
// check to see if the device even has room for all the overlays, moving some to overflow if not
int widthPX = findViewById(android.R.id.content).getMeasuredWidth();
boolean overflowExtras = false;
if (widthPX != 0) {
float widthDP = UIUtils.px2dp(this, widthPX);
if ( widthDP < OVERLAY_MIN_WIDTH_DP ){
overflowExtras = true;
}
}
UIUtils.setViewAlpha(this.overlayLeft, a, true);
UIUtils.setViewAlpha(this.overlayRight, a, true);
UIUtils.setViewAlpha(this.overlayProgress, a, true);
UIUtils.setViewAlpha(this.overlayText, a, true);
UIUtils.setViewAlpha(this.overlaySend, a, !overflowExtras);
}
/**
@ -332,16 +339,8 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
* an event happens that might change our list position.
*/
private void enableOverlays() {
// check to see if the device even has room for all the overlays, moving some to overflow if not
int widthPX = findViewById(android.R.id.content).getMeasuredWidth();
if (widthPX != 0) {
float widthDP = UIUtils.px2dp(this, widthPX);
if ( widthDP < OVERLAY_MIN_WIDTH_DP ){
this.overlaySend.setVisibility(View.GONE);
} else {
this.overlaySend.setVisibility(View.VISIBLE);
}
}
this.setOverlayAlpha(1.0f);
this.overlayLeft.setEnabled(this.getLastReadPosition(false) != -1);
this.overlayRight.setText((this.currentUnreadCount > 0) ? R.string.overlay_next : R.string.overlay_done);
@ -370,7 +369,6 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
invalidateOptionsMenu();
this.setOverlayAlpha(1.0f);
}
public void onWindowFocusChanged(boolean hasFocus) {

View file

@ -129,7 +129,9 @@ public class FeedProvider extends ContentProvider {
return 1;
case ALL_STORIES:
return db.delete(DatabaseConstants.STORY_TABLE, null, null);
db.delete(DatabaseConstants.STORY_TABLE, null, null);
db.delete(DatabaseConstants.STARRED_STORIES_TABLE, null, null);
return 1;
case SOCIALFEED_STORIES:
StringBuilder socialDeleteBuilder = new StringBuilder();

View file

@ -22,6 +22,7 @@ public abstract class ItemListFragment extends Fragment implements OnScrollListe
protected boolean requestedPage;
protected StoryItemsAdapter adapter;
protected DefaultFeedView defaultFeedView;
private boolean firstSyncDone = false;
public abstract void hasUpdated();
public abstract void changeState(final int state);
@ -32,7 +33,11 @@ public abstract class ItemListFragment extends Fragment implements OnScrollListe
this.currentPage = 0;
}
public void setEmptyListView(int rid) {
public void syncDone() {
this.firstSyncDone = true;
}
private void finishLoadingScreen() {
View v = this.getView();
if (v == null) return; // we might have beat construction?
@ -43,12 +48,13 @@ public abstract class ItemListFragment extends Fragment implements OnScrollListe
}
TextView emptyView = (TextView) itemList.getEmptyView();
emptyView.setText(rid);
emptyView.setText(R.string.empty_list_view_no_stories);
}
@Override
public synchronized void onScroll(AbsListView view, int firstVisible, int visibleCount, int totalCount) {
if (totalCount != 0 && (firstVisible + visibleCount == totalCount) && !requestedPage) {
// load an extra page worth of stories past the viewport
if (totalCount != 0 && (firstVisible + visibleCount + visibleCount - 1 >= totalCount) && !requestedPage) {
currentPage += 1;
requestedPage = true;
triggerRefresh(currentPage);
@ -71,6 +77,11 @@ public abstract class ItemListFragment extends Fragment implements OnScrollListe
triggerRefresh(currentPage);
}
adapter.swapCursor(cursor);
// iff a sync has finished and a cursor load has finished, it is safe to remove the loading message
if (this.firstSyncDone) {
finishLoadingScreen();
}
}
}

View file

@ -60,6 +60,7 @@ public class APIManager {
private Context context;
private Gson gson;
private ContentResolver contentResolver;
private String customUserAgent;
public APIManager(final Context context) {
this.context = context;
@ -69,6 +70,14 @@ public class APIManager {
.registerTypeAdapter(Boolean.class, new BooleanTypeAdapter())
.registerTypeAdapter(boolean.class, new BooleanTypeAdapter())
.create();
String appVersion = context.getSharedPreferences(PrefConstants.PREFERENCES, 0).getString(AppConstants.LAST_APP_VERSION, "unknown_version");
this.customUserAgent = "NewsBlur Android app" +
" (" + Build.MANUFACTURER + " " +
Build.MODEL + " " +
Build.VERSION.RELEASE + " " +
appVersion + ")";
}
public NewsBlurResponse login(final String username, final String password) {
@ -692,13 +701,7 @@ public class APIManager {
if (cookie != null) {
connection.setRequestProperty("Cookie", cookie);
}
// PackageManager manager = context.getPackageManager();
// PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
connection.setRequestProperty("User-Agent", "NewsBlur Android app" +
" (" + Build.MANUFACTURER + " " +
Build.MODEL + " " +
Build.VERSION.RELEASE + ")");
connection.setRequestProperty("User-Agent", this.customUserAgent);
return new APIResponse(context, url, connection);
} catch (IOException e) {
Log.e(this.getClass().getName(), "Error opening GET connection to " + urlString, e.getCause());

View file

@ -1,5 +1,7 @@
package com.newsblur.network.domain;
import android.util.Log;
/**
* A generic response to an API call that only encapsuates success versus failure.
*/
@ -12,8 +14,14 @@ public class NewsBlurResponse {
public String result;
public boolean isError() {
if ((message != null) && (!message.equals(""))) return true;
if ((errors != null) && (errors.message.length > 0) && (errors.message[0] != null)) return true;
if ((message != null) && (!message.equals(""))) {
Log.d(this.getClass().getName(), "Response interpreted as error due to 'message' field: " + message);
return true;
}
if ((errors != null) && (errors.message.length > 0) && (errors.message[0] != null)) {
Log.d(this.getClass().getName(), "Response interpreted as error due to 'ResponseErrors' field: " + errors.message[0]);
return true;
}
return false;
}

View file

@ -118,22 +118,24 @@ public class FeedUtils {
}
private static void handleStoryResponse(Context context, NewsBlurResponse response, Story[] stories, ActionCompletionListener receiver) {
// NB: we do not keep loading on error, since the calling class would need to know to adjust pagination
// the API may return both a valid stories block *and* an error, so check for stories first
if (stories != null) {
if (receiver != null) {
receiver.actionCompleteCallback(stories.length == 0); // only keep loading if there are more stories left
}
return;
}
if (response.isError()) {
Log.e(FeedUtils.class.getName(), "Error response received loading stories.");
Toast.makeText(context, response.getErrorMessage(context.getString(R.string.toast_error_loading_stories)), Toast.LENGTH_LONG).show();
} else {
Log.e(FeedUtils.class.getName(), "Null stories member received while loading stories with no error found.");
Toast.makeText(context, R.string.toast_error_loading_stories, Toast.LENGTH_LONG).show();
receiver.actionCompleteCallback(true);
return;
}
if (stories == null) {
Log.e(FeedUtils.class.getName(), "Null stories member received loading stories.");
Toast.makeText(context, R.string.toast_error_loading_stories, Toast.LENGTH_LONG).show();
receiver.actionCompleteCallback(true);
return;
}
if (receiver != null) {
receiver.actionCompleteCallback(stories.length == 0); // only keep loading if there are more stories left
}
// NB: we do not keep loading on error, since the calling class would need to know to adjust pagination
receiver.actionCompleteCallback(true);
}
private static void setStorySaved(final Story story, final boolean saved, final Context context, final APIManager apiManager, final ActionCompletionListener receiver) {

View file

@ -83,13 +83,15 @@ public class UIUtils {
}
/**
* Sets the alpha of a view in a manner that is safe to use before API version 11.
* If alpha isn't supported, just make the view invisible if the alpha is so low
* that it may as well be.
* Sets the alpha of a view, totally hiding the view if the alpha is so low
* as to be invisible, but also obeying intended visibility.
*/
public static void setViewAlpha(View v, float alpha) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
v.setAlpha(alpha);
public static void setViewAlpha(View v, float alpha, boolean visible) {
v.setAlpha(alpha);
if ((alpha < 0.001f) || !visible) {
v.setVisibility(View.GONE);
} else {
v.setVisibility(View.VISIBLE);
}
}