diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiCommon.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiCommon.java new file mode 100644 index 00000000..e2cc4174 --- /dev/null +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiCommon.java @@ -0,0 +1,81 @@ +package org.fox.ttrss; + +import android.os.Build; + +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +/** + * Created by andrew on 31.05.2017. + */ + +public class ApiCommon { + public enum ApiError { NO_ERROR, HTTP_UNAUTHORIZED, HTTP_FORBIDDEN, HTTP_NOT_FOUND, + HTTP_SERVER_ERROR, HTTP_OTHER_ERROR, SSL_REJECTED, SSL_HOSTNAME_REJECTED, PARSE_ERROR, IO_ERROR, OTHER_ERROR, API_DISABLED, + API_UNKNOWN, LOGIN_FAILED, INVALID_URL, API_INCORRECT_USAGE, NETWORK_UNAVAILABLE, API_UNKNOWN_METHOD } + + public static void trustAllHosts(boolean trustAnyCert, boolean trustAnyHost) { + try { + if (trustAnyCert) { + X509TrustManager easyTrustManager = new X509TrustManager() { + + public void checkClientTrusted( + X509Certificate[] chain, + String authType) throws CertificateException { + // Oh, I am easy! + } + + public void checkServerTrusted( + X509Certificate[] chain, + String authType) throws CertificateException { + // Oh, I am easy! + } + + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + }; + + // Create a trust manager that does not validate certificate chains + TrustManager[] trustAllCerts = new TrustManager[] {easyTrustManager}; + + // Install the all-trusting trust manager + + SSLContext sc = SSLContext.getInstance("TLS"); + + sc.init(null, trustAllCerts, new java.security.SecureRandom()); + + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } + + if (trustAnyHost) { + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + @SuppressWarnings("deprecation") + protected static void disableConnectionReuseIfNecessary() { + // HTTP connection reuse which was buggy pre-froyo + if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) { + System.setProperty("http.keepAlive", "false"); + } + } + +} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiLoader.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiLoader.java new file mode 100644 index 00000000..66cbb674 --- /dev/null +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiLoader.java @@ -0,0 +1,284 @@ +package org.fox.ttrss; + +import android.content.Context; +import android.content.SharedPreferences; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.preference.PreferenceManager; +import android.support.v4.content.AsyncTaskLoader; +import android.util.Base64; +import android.util.Log; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import org.fox.ttrss.ApiCommon.ApiError; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; + +public class ApiLoader extends AsyncTaskLoader { + private final String TAG = this.getClass().getSimpleName(); + + + public static final int API_STATUS_OK = 0; + public static final int API_STATUS_ERR = 1; + + private String m_api; + private boolean m_transportDebugging = false; + protected int m_responseCode = 0; + protected String m_responseMessage; + protected int m_apiStatusCode = 0; + protected boolean m_canUseProgress = false; + protected Context m_context; + private SharedPreferences m_prefs; + protected String m_lastErrorMessage; + protected ApiError m_lastError; + protected HashMap m_params; + + public ApiLoader(Context context, HashMap params) { + super(context); + + m_context = context; + + m_prefs = PreferenceManager.getDefaultSharedPreferences(m_context); + + m_api = m_prefs.getString("ttrss_url", "").trim(); + m_transportDebugging = m_prefs.getBoolean("transport_debugging", false); + m_lastError = ApiError.NO_ERROR; + m_params = params; + + } + + public int getErrorMessage() { + switch (m_lastError) { + case NO_ERROR: + return R.string.error_unknown; + case HTTP_UNAUTHORIZED: + return R.string.error_http_unauthorized; + case HTTP_FORBIDDEN: + return R.string.error_http_forbidden; + case HTTP_NOT_FOUND: + return R.string.error_http_not_found; + case HTTP_SERVER_ERROR: + return R.string.error_http_server_error; + case HTTP_OTHER_ERROR: + return R.string.error_http_other_error; + case SSL_REJECTED: + return R.string.error_ssl_rejected; + case SSL_HOSTNAME_REJECTED: + return R.string.error_ssl_hostname_rejected; + case PARSE_ERROR: + return R.string.error_parse_error; + case IO_ERROR: + return R.string.error_io_error; + case OTHER_ERROR: + return R.string.error_other_error; + case API_DISABLED: + return R.string.error_api_disabled; + case API_UNKNOWN: + return R.string.error_api_unknown; + case API_UNKNOWN_METHOD: + return R.string.error_api_unknown_method; + case LOGIN_FAILED: + return R.string.error_login_failed; + case INVALID_URL: + return R.string.error_invalid_api_url; + case API_INCORRECT_USAGE: + return R.string.error_api_incorrect_usage; + case NETWORK_UNAVAILABLE: + return R.string.error_network_unavailable; + default: + Log.d(TAG, "getErrorMessage: unknown error code=" + m_lastError); + return R.string.error_unknown; + } + } + + public ApiError getLastError() { + return m_lastError; + } + + public String getLastErrorMessage() { + return m_lastErrorMessage; + } + + @Override + public JsonElement loadInBackground() { + + if (!isNetworkAvailable()) { + m_lastError = ApiError.NETWORK_UNAVAILABLE; + return null; + } + + Gson gson = new Gson(); + + String requestStr = gson.toJson(new HashMap<>(m_params)); + byte[] postData = null; + + try { + postData = requestStr.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + m_lastError = ApiError.OTHER_ERROR; + e.printStackTrace(); + return null; + } + + if (m_transportDebugging) Log.d(TAG, ">>> (" + requestStr + ") " + m_api); + + URL url; + + try { + url = new URL(m_api + "/api/"); + } catch (Exception e) { + m_lastError = ApiError.INVALID_URL; + e.printStackTrace(); + return null; + } + + try { + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + + String httpLogin = m_prefs.getString("http_login", "").trim(); + String httpPassword = m_prefs.getString("http_password", "").trim(); + + if (httpLogin.length() > 0) { + if (m_transportDebugging) Log.d(TAG, "Using HTTP Basic authentication."); + + conn.setRequestProperty("Authorization", "Basic " + + Base64.encodeToString((httpLogin + ":" + httpPassword).getBytes("UTF-8"), Base64.NO_WRAP)); + } + + conn.setDoInput(true); + conn.setDoOutput(true); + conn.setUseCaches(false); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Length", Integer.toString(postData.length)); + + OutputStream out = conn.getOutputStream(); + out.write(postData); + out.close(); + + m_responseCode = conn.getResponseCode(); + m_responseMessage = conn.getResponseMessage(); + + switch (m_responseCode) { + case HttpURLConnection.HTTP_OK: + StringBuffer response = new StringBuffer(); + InputStreamReader in = new InputStreamReader(conn.getInputStream(), "UTF-8"); + char[] buf = new char[256]; + int read = 0; + int total = 0; + + int contentLength = conn.getHeaderFieldInt("Api-Content-Length", -1); + + m_canUseProgress = (contentLength != -1); + + while ((read = in.read(buf)) >= 0) { + response.append(buf, 0, read); + total += read; + //publishProgress(Integer.valueOf(total), Integer.valueOf(contentLength)); + } + + if (m_transportDebugging) Log.d(TAG, "<<< " + response); + + JsonParser parser = new JsonParser(); + + JsonElement result = parser.parse(response.toString()); + JsonObject resultObj = result.getAsJsonObject(); + + m_apiStatusCode = resultObj.get("status").getAsInt(); + + conn.disconnect(); + + switch (m_apiStatusCode) { + case API_STATUS_OK: + return result.getAsJsonObject().get("content"); + case API_STATUS_ERR: + JsonObject contentObj = resultObj.get("content").getAsJsonObject(); + String error = contentObj.get("error").getAsString(); + + if (error.equals("LOGIN_ERROR")) { + m_lastError = ApiError.LOGIN_FAILED; + } else if (error.equals("API_DISABLED")) { + m_lastError = ApiError.API_DISABLED; + } else if (error.equals("NOT_LOGGED_IN")) { + m_lastError = ApiError.LOGIN_FAILED; + } else if (error.equals("INCORRECT_USAGE")) { + m_lastError = ApiError.API_INCORRECT_USAGE; + } else if (error.equals("UNKNOWN_METHOD")) { + m_lastError = ApiError.API_UNKNOWN_METHOD; + } else { + Log.d(TAG, "Unknown API error: " + error); + m_lastError = ApiError.API_UNKNOWN; + } + } + + return null; + case HttpURLConnection.HTTP_UNAUTHORIZED: + m_lastError = ApiError.HTTP_UNAUTHORIZED; + break; + case HttpURLConnection.HTTP_FORBIDDEN: + m_lastError = ApiError.HTTP_FORBIDDEN; + break; + case HttpURLConnection.HTTP_NOT_FOUND: + m_lastError = ApiError.HTTP_NOT_FOUND; + break; + case HttpURLConnection.HTTP_INTERNAL_ERROR: + m_lastError = ApiError.HTTP_SERVER_ERROR; + break; + default: + Log.d(TAG, "HTTP response code: " + m_responseCode + "(" + m_responseMessage + ")"); + m_lastError = ApiError.HTTP_OTHER_ERROR; + break; + } + + conn.disconnect(); + return null; + } catch (javax.net.ssl.SSLPeerUnverifiedException e) { + m_lastError = ApiError.SSL_REJECTED; + m_lastErrorMessage = e.getMessage(); + e.printStackTrace(); + } catch (IOException e) { + m_lastError = ApiError.IO_ERROR; + m_lastErrorMessage = e.getMessage(); + + if (e.getMessage() != null) { + if (e.getMessage().matches("Hostname [^ ]+ was not verified")) { + m_lastError = ApiError.SSL_HOSTNAME_REJECTED; + } + } + + e.printStackTrace(); + } catch (com.google.gson.JsonSyntaxException e) { + m_lastError = ApiError.PARSE_ERROR; + m_lastErrorMessage = e.getMessage(); + e.printStackTrace(); + } catch (Exception e) { + m_lastError = ApiError.OTHER_ERROR; + m_lastErrorMessage = e.getMessage(); + e.printStackTrace(); + } + + return null; + } + + protected boolean isNetworkAvailable() { + ConnectivityManager cm = (ConnectivityManager) + m_context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo networkInfo = cm.getActiveNetworkInfo(); + + // if no network is available networkInfo will be null + // otherwise check if we are connected + if (networkInfo != null && networkInfo.isConnected()) { + return true; + } + return false; + } +} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiRequest.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiRequest.java index 03a2769f..b001e012 100644 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiRequest.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiRequest.java @@ -22,24 +22,13 @@ import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; import java.util.HashMap; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; +import static org.fox.ttrss.ApiCommon.ApiError; public class ApiRequest extends AsyncTask, Integer, JsonElement> { private final String TAG = this.getClass().getSimpleName(); - public enum ApiError { NO_ERROR, HTTP_UNAUTHORIZED, HTTP_FORBIDDEN, HTTP_NOT_FOUND, - HTTP_SERVER_ERROR, HTTP_OTHER_ERROR, SSL_REJECTED, SSL_HOSTNAME_REJECTED, PARSE_ERROR, IO_ERROR, OTHER_ERROR, API_DISABLED, - API_UNKNOWN, LOGIN_FAILED, INVALID_URL, API_INCORRECT_USAGE, NETWORK_UNAVAILABLE, API_UNKNOWN_METHOD } - public static final int API_STATUS_OK = 0; public static final int API_STATUS_ERR = 1; @@ -140,13 +129,8 @@ public class ApiRequest extends AsyncTask, Integer, JsonE return null; } - /* disableConnectionReuseIfNecessary(); */ - if (m_transportDebugging) Log.d(TAG, ">>> (" + requestStr + ") " + m_api); - /* ApiRequest.trustAllHosts(m_prefs.getBoolean("ssl_trust_any", false), - m_prefs.getBoolean("ssl_trust_any_host", false)); */ - URL url; try { @@ -283,64 +267,7 @@ public class ApiRequest extends AsyncTask, Integer, JsonE return null; } - - public static void trustAllHosts(boolean trustAnyCert, boolean trustAnyHost) { - try { - if (trustAnyCert) { - X509TrustManager easyTrustManager = new X509TrustManager() { - public void checkClientTrusted( - X509Certificate[] chain, - String authType) throws CertificateException { - // Oh, I am easy! - } - - public void checkServerTrusted( - X509Certificate[] chain, - String authType) throws CertificateException { - // Oh, I am easy! - } - - public X509Certificate[] getAcceptedIssuers() { - return null; - } - - }; - - // Create a trust manager that does not validate certificate chains - TrustManager[] trustAllCerts = new TrustManager[] {easyTrustManager}; - - // Install the all-trusting trust manager - - SSLContext sc = SSLContext.getInstance("TLS"); - - sc.init(null, trustAllCerts, new java.security.SecureRandom()); - - HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); - } - - if (trustAnyHost) { - HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; - } - }); - } - - } catch (Exception e) { - e.printStackTrace(); - } - } - - @SuppressWarnings("deprecation") - protected static void disableConnectionReuseIfNecessary() { - // HTTP connection reuse which was buggy pre-froyo - if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) { - System.setProperty("http.keepAlive", "false"); - } - } - protected boolean isNetworkAvailable() { ConnectivityManager cm = (ConnectivityManager) m_context.getSystemService(Context.CONNECTIVITY_SERVICE); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticlePager.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticlePager.java index 6e51722c..1fb918ed 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticlePager.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticlePager.java @@ -3,7 +3,6 @@ package org.fox.ttrss; import android.annotation.SuppressLint; import android.app.Activity; import android.content.SharedPreferences; -import android.net.Uri; import android.os.BadParcelableException; import android.os.Bundle; import android.os.Handler; @@ -209,7 +208,7 @@ public class ArticlePager extends Fragment { } } else { - if (m_lastError == ApiError.LOGIN_FAILED) { + if (m_lastError == ApiCommon.ApiError.LOGIN_FAILED) { m_activity.login(true); } else { m_activity.toast(getErrorMessage()); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedCategoriesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedCategoriesFragment.java index bf0b19b4..3796b765 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedCategoriesFragment.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedCategoriesFragment.java @@ -10,6 +10,8 @@ import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.Loader; import android.support.v4.widget.SwipeRefreshLayout; import android.util.Log; import android.util.TypedValue; @@ -43,7 +45,8 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; -public class FeedCategoriesFragment extends BaseFeedlistFragment implements OnItemClickListener, OnSharedPreferenceChangeListener { +public class FeedCategoriesFragment extends BaseFeedlistFragment implements OnItemClickListener, OnSharedPreferenceChangeListener, + LoaderManager.LoaderCallbacks { private final String TAG = this.getClass().getSimpleName(); private FeedCategoryListAdapter m_adapter; private FeedCategoryList m_cats = new FeedCategoryList(); @@ -53,6 +56,131 @@ public class FeedCategoriesFragment extends BaseFeedlistFragment implements OnIt private ListView m_list; protected SharedPreferences m_prefs; + @Override + public Loader onCreateLoader(int id, Bundle args) { + final String sessionId = m_activity.getSessionId(); + final boolean unreadOnly = m_activity.getUnreadOnly(); + + @SuppressWarnings("serial") + HashMap params = new HashMap() { + { + put("op", "getCategories"); + put("sid", sessionId); + put("enable_nested", "true"); + if (unreadOnly) { + put("unread_only", String.valueOf(unreadOnly)); + } + } + }; + + return new ApiLoader(getContext(), params); + } + + @Override + public void onLoadFinished(Loader loader, JsonElement result) { + Log.d(TAG, "onLoadFinished: " + loader + " " + result); + + if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false); + + View loadingBar = getView().findViewById(R.id.feeds_loading_bar); + + if (loadingBar != null) { + loadingBar.setVisibility(View.INVISIBLE); + } + + if (result != null) { + try { + JsonArray content = result.getAsJsonArray(); + if (content != null) { + Type listType = new TypeToken>() {}.getType(); + final List cats = new Gson().fromJson(content, listType); + + m_cats.clear(); + + int apiLevel = m_activity.getApiLevel(); + + boolean specialCatFound = false; + + // virtual cats implemented in getCategories since api level 1 + if (apiLevel == 0) { + m_cats.add(new FeedCategory(-1, "Special", 0)); + m_cats.add(new FeedCategory(-2, "Labels", 0)); + m_cats.add(new FeedCategory(0, "Uncategorized", 0)); + + specialCatFound = true; + } + + for (FeedCategory c : cats) { + if (c.id == -1) { + specialCatFound = true; + } + + m_cats.add(c); + } + + sortCats(); + + if (!specialCatFound) { + m_cats.add(0, new FeedCategory(-1, "Special", 0)); + } + + //m_adapter.notifyDataSetChanged(); (done by sortCats) + //m_activity.setLoadingStatus(R.string.blank, false); + + return; + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + ApiLoader al = (ApiLoader) loader; + + if (al.getLastError() == ApiCommon.ApiError.LOGIN_FAILED) { + m_activity.login(true); + } else { + if (al.getLastErrorMessage() != null) { + m_activity.toast(getString(al.getErrorMessage()) + "\n" + al.getLastErrorMessage()); + } else { + m_activity.toast(al.getErrorMessage()); + } + } + } + + public void sortCats() { + Comparator cmp; + + if (m_prefs.getBoolean("sort_feeds_by_unread", false)) { + cmp = new CatUnreadComparator(); + } else { + if (m_activity.getApiLevel() >= 3) { + cmp = new CatOrderComparator(); + } else { + cmp = new CatTitleComparator(); + } + } + + try { + Collections.sort(m_cats, cmp); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + try { + m_adapter.notifyDataSetChanged(); + } catch (NullPointerException e) { + // adapter missing + } + } + + @Override + public void onLoaderReset(Loader loader) { + Log.d(TAG, "onLoaderReset: " + loader); + + m_cats.clear(); + m_adapter.notifyDataSetChanged(); + } + @SuppressLint("DefaultLocale") class CatUnreadComparator implements Comparator { @Override @@ -248,8 +376,10 @@ public class FeedCategoriesFragment extends BaseFeedlistFragment implements OnIt public void onResume() { super.onResume(); - refresh(false); - + //refresh(false); + + getLoaderManager().initLoader(0, null, this).forceLoad(); + m_activity.invalidateOptionsMenu(); } @@ -262,164 +392,12 @@ public class FeedCategoriesFragment extends BaseFeedlistFragment implements OnIt out.putParcelable("cats", m_cats); } - /* private void setLoadingStatus(int status, boolean showProgress) { - if (getView() != null) { - TextView tv = (TextView)getView().findViewById(R.id.loading_message); - - if (tv != null) { - tv.setText(status); - } - } - - m_activity.setProgressBarIndeterminateVisibility(showProgress); - } */ - public void refresh(boolean background) { if (!isAdded()) return; if (m_swipeLayout != null) m_swipeLayout.setRefreshing(true); - - CatsRequest req = new CatsRequest(getActivity().getApplicationContext()); - - final String sessionId = m_activity.getSessionId(); - final boolean unreadOnly = m_activity.getUnreadOnly(); - - if (sessionId != null) { - //m_activity.setLoadingStatus(R.string.blank, true); - //m_activity.setProgressBarVisibility(true); - - @SuppressWarnings("serial") - HashMap map = new HashMap() { - { - put("op", "getCategories"); - put("sid", sessionId); - put("enable_nested", "true"); - if (unreadOnly) { - put("unread_only", String.valueOf(unreadOnly)); - } - } - }; - req.execute(map); - } - } - - private class CatsRequest extends ApiRequest { - - public CatsRequest(Context context) { - super(context); - } - - @Override - protected void onProgressUpdate(Integer... progress) { - m_activity.setProgress(Math.round((((float)progress[0] / (float)progress[1]) * 10000))); - } - - @Override - protected void onPostExecute(JsonElement result) { - if (isDetached() || !isAdded()) return; - - if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false); - - if (getView() != null) { - View loadingBar = getView().findViewById(R.id.feeds_loading_bar); - - if (loadingBar != null) { - loadingBar.setVisibility(View.INVISIBLE); - } - } - - if (result != null) { - try { - JsonArray content = result.getAsJsonArray(); - if (content != null) { - Type listType = new TypeToken>() {}.getType(); - final List cats = new Gson().fromJson(content, listType); - - m_cats.clear(); - - int apiLevel = m_activity.getApiLevel(); - - boolean specialCatFound = false; - - // virtual cats implemented in getCategories since api level 1 - if (apiLevel == 0) { - m_cats.add(new FeedCategory(-1, "Special", 0)); - m_cats.add(new FeedCategory(-2, "Labels", 0)); - m_cats.add(new FeedCategory(0, "Uncategorized", 0)); - - specialCatFound = true; - } - - for (FeedCategory c : cats) { - if (c.id == -1) { - specialCatFound = true; - } - - m_cats.add(c); - } - - sortCats(); - - if (!specialCatFound) { - m_cats.add(0, new FeedCategory(-1, "Special", 0)); - } - - /* if (m_cats.size() == 0) - setLoadingStatus(R.string.no_feeds_to_display, false); - else */ - - //m_adapter.notifyDataSetChanged(); (done by sortCats) - //m_activity.setLoadingStatus(R.string.blank, false); - - return; - } - - } catch (Exception e) { - e.printStackTrace(); - } - } - - if (m_lastError == ApiError.LOGIN_FAILED) { - m_activity.login(true); - } else { - - if (m_lastErrorMessage != null) { - m_activity.toast(getString(getErrorMessage()) + "\n" + m_lastErrorMessage); - } else { - m_activity.toast(getErrorMessage()); - } - - //m_activity.setLoadingStatus(getErrorMessage(), false); - } - } - - } - - public void sortCats() { - Comparator cmp; - - if (m_prefs.getBoolean("sort_feeds_by_unread", false)) { - cmp = new CatUnreadComparator(); - } else { - if (m_activity.getApiLevel() >= 3) { - cmp = new CatOrderComparator(); - } else { - cmp = new CatTitleComparator(); - } - } - - try { - Collections.sort(m_cats, cmp); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } - try { - m_adapter.notifyDataSetChanged(); - } catch (NullPointerException e) { - // adapter missing - } - + getLoaderManager().restartLoader(0, null, this).forceLoad(); } private class FeedCategoryListAdapter extends ArrayAdapter { diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java index 5e52ba4a..591088b4 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java @@ -569,7 +569,7 @@ public class FeedsFragment extends BaseFeedlistFragment implements OnItemClickLi } } - if (m_lastError == ApiError.LOGIN_FAILED) { + if (m_lastError == ApiCommon.ApiError.LOGIN_FAILED) { m_activity.login(true); } else { diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java index 880bf384..10fea096 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java @@ -36,7 +36,6 @@ import android.view.Display; import android.view.LayoutInflater; import android.view.MenuInflater; import android.view.MenuItem; -import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -63,7 +62,6 @@ import com.nhaarman.listviewanimations.appearance.simple.SwingBottomInAnimationA import com.nhaarman.listviewanimations.itemmanipulation.DynamicListView; import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.DismissableManager; import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.OnDismissCallback; -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.undo.SimpleSwipeUndoAdapter; import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.undo.TimedUndoAdapter; import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.undo.UndoAdapter; import com.nostra13.universalimageloader.core.DisplayImageOptions; @@ -751,7 +749,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener, //m_listLoadingView.setVisibility(m_amountLoaded == HEADLINES_REQUEST_SIZE ? View.VISIBLE : View.GONE); } else { - if (m_lastError == ApiError.LOGIN_FAILED) { + if (m_lastError == ApiCommon.ApiError.LOGIN_FAILED) { m_activity.login(true); } else { diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/OnlineActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/OnlineActivity.java index b00b829f..a7d42739 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/OnlineActivity.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/OnlineActivity.java @@ -136,7 +136,7 @@ public class OnlineActivity extends CommonActivity { @Override public void onCreate(Bundle savedInstanceState) { - ApiRequest.disableConnectionReuseIfNecessary(); + ApiCommon.disableConnectionReuseIfNecessary(); // we use that before parent onCreate so let's init locally m_prefs = PreferenceManager @@ -1184,7 +1184,7 @@ public class OnlineActivity extends CommonActivity { public void onResume() { super.onResume(); - ApiRequest.trustAllHosts(m_prefs.getBoolean("ssl_trust_any", false), + ApiCommon.trustAllHosts(m_prefs.getBoolean("ssl_trust_any", false), m_prefs.getBoolean("ssl_trust_any_host", false)); IntentFilter filter = new IntentFilter(); @@ -1581,7 +1581,7 @@ public class OnlineActivity extends CommonActivity { } catch (Exception e) { e.printStackTrace(); } - } else if (m_lastError != ApiError.API_UNKNOWN_METHOD) { + } else if (m_lastError != ApiCommon.ApiError.API_UNKNOWN_METHOD) { // Unknown method means old tt-rss, in that case we assume API 0 and continue setLoadingStatus(getErrorMessage(), false); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/share/ShareActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/share/ShareActivity.java index 85e18b6b..46e89b28 100644 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/share/ShareActivity.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/share/ShareActivity.java @@ -9,6 +9,7 @@ import android.widget.EditText; import com.google.gson.JsonElement; +import org.fox.ttrss.ApiCommon; import org.fox.ttrss.ApiRequest; import org.fox.ttrss.R; @@ -95,7 +96,7 @@ public class ShareActivity extends CommonShareActivity { protected void onPostExecute(JsonElement result) { setProgressBarIndeterminateVisibility(false); - if (m_lastError != ApiError.NO_ERROR) { + if (m_lastError != ApiCommon.ApiError.NO_ERROR) { toast(getErrorMessage()); } else { toast(R.string.share_article_posted); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/share/SubscribeActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/share/SubscribeActivity.java index a3b7d060..9b92630a 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/share/SubscribeActivity.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/share/SubscribeActivity.java @@ -18,6 +18,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; +import org.fox.ttrss.ApiCommon; import org.fox.ttrss.ApiRequest; import org.fox.ttrss.R; import org.fox.ttrss.types.FeedCategory; @@ -168,7 +169,7 @@ public class SubscribeActivity extends CommonShareActivity { protected void onPostExecute(JsonElement result) { m_progressBar.setVisibility(View.INVISIBLE); - if (m_lastError != ApiError.NO_ERROR) { + if (m_lastError != ApiCommon.ApiError.NO_ERROR) { toast(getErrorMessage()); } else { try { @@ -273,7 +274,7 @@ public class SubscribeActivity extends CommonShareActivity { protected void onPostExecute(JsonElement result) { m_progressBar.setVisibility(View.INVISIBLE); - if (m_lastError != ApiError.NO_ERROR) { + if (m_lastError != ApiCommon.ApiError.NO_ERROR) { toast(getErrorMessage()); } else { JsonArray content = result.getAsJsonArray(); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/tasker/TaskerReceiver.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/tasker/TaskerReceiver.java index 4b6d81a9..6d521022 100644 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/tasker/TaskerReceiver.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/tasker/TaskerReceiver.java @@ -1,5 +1,6 @@ package org.fox.ttrss.tasker; +import org.fox.ttrss.ApiCommon; import org.fox.ttrss.ApiRequest; import org.fox.ttrss.CommonActivity; import org.fox.ttrss.OnlineActivity; @@ -80,7 +81,7 @@ public class TaskerReceiver extends BroadcastReceiver { String login = prefs.getString("login", "").trim(); String password = prefs.getString("password", "").trim(); String ttrssUrl = prefs.getString("ttrss_url", "").trim(); - ApiRequest.trustAllHosts(prefs.getBoolean("ssl_trust_any", false), prefs.getBoolean("ssl_trust_any_host", false)); + ApiCommon.trustAllHosts(prefs.getBoolean("ssl_trust_any", false), prefs.getBoolean("ssl_trust_any_host", false)); if (ttrssUrl.equals("")) { Toast toast = Toast.makeText(fContext, "Could not download articles: not configured?", Toast.LENGTH_SHORT); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/util/HeadlinesRequest.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/util/HeadlinesRequest.java index 54df9da4..8cb1a3c1 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/util/HeadlinesRequest.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/util/HeadlinesRequest.java @@ -9,8 +9,8 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; +import org.fox.ttrss.ApiCommon; import org.fox.ttrss.ApiRequest; -import org.fox.ttrss.HeadlinesFragment; import org.fox.ttrss.OnlineActivity; import org.fox.ttrss.types.Article; import org.fox.ttrss.types.ArticleList; @@ -121,7 +121,7 @@ public class HeadlinesRequest extends ApiRequest { } } - if (m_lastError == ApiError.LOGIN_FAILED) { + if (m_lastError == ApiCommon.ApiError.LOGIN_FAILED) { m_activity.login(); } else {