From ad12b2b945d23af48d3930c1602971dc8e4924d8 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 24 Mar 2013 19:43:03 +0400 Subject: integrate share app stuff into tt-rss app --- src/org/fox/ttrss/OnlineActivity.java | 6 + src/org/fox/ttrss/share/CommonActivity.java | 57 +++++ src/org/fox/ttrss/share/CommonShareActivity.java | 186 +++++++++++++++ src/org/fox/ttrss/share/FeedCategory.java | 58 +++++ src/org/fox/ttrss/share/FeedCategoryList.java | 52 +++++ src/org/fox/ttrss/share/ShareActivity.java | 146 ++++++++++++ src/org/fox/ttrss/share/SubscribeActivity.java | 275 +++++++++++++++++++++++ 7 files changed, 780 insertions(+) create mode 100644 src/org/fox/ttrss/share/CommonActivity.java create mode 100644 src/org/fox/ttrss/share/CommonShareActivity.java create mode 100644 src/org/fox/ttrss/share/FeedCategory.java create mode 100644 src/org/fox/ttrss/share/FeedCategoryList.java create mode 100644 src/org/fox/ttrss/share/ShareActivity.java create mode 100644 src/org/fox/ttrss/share/SubscribeActivity.java (limited to 'src') diff --git a/src/org/fox/ttrss/OnlineActivity.java b/src/org/fox/ttrss/OnlineActivity.java index 3c52fdf9..ca5dff0f 100644 --- a/src/org/fox/ttrss/OnlineActivity.java +++ b/src/org/fox/ttrss/OnlineActivity.java @@ -7,6 +7,7 @@ import java.util.List; import org.fox.ttrss.offline.OfflineActivity; import org.fox.ttrss.offline.OfflineDownloadService; import org.fox.ttrss.offline.OfflineUploadService; +import org.fox.ttrss.share.SubscribeActivity; import org.fox.ttrss.types.Article; import org.fox.ttrss.types.ArticleList; import org.fox.ttrss.types.Feed; @@ -561,6 +562,10 @@ public class OnlineActivity extends CommonActivity { case android.R.id.home: finish(); return true; + case R.id.subscribe_to_feed: + Intent subscribe = new Intent(OnlineActivity.this, SubscribeActivity.class); + startActivityForResult(subscribe, 0); + return true; case R.id.toggle_attachments: if (true) { Article article = ap.getSelectedArticle(); @@ -1311,6 +1316,7 @@ public class OnlineActivity extends CommonActivity { m_menu.findItem(R.id.set_labels).setEnabled(getApiLevel() >= 1); m_menu.findItem(R.id.article_set_note).setEnabled(getApiLevel() >= 1); + m_menu.findItem(R.id.subscribe_to_feed).setEnabled(getApiLevel() >= 5); MenuItem search = m_menu.findItem(R.id.search); search.setEnabled(getApiLevel() >= 2); diff --git a/src/org/fox/ttrss/share/CommonActivity.java b/src/org/fox/ttrss/share/CommonActivity.java new file mode 100644 index 00000000..808bd31e --- /dev/null +++ b/src/org/fox/ttrss/share/CommonActivity.java @@ -0,0 +1,57 @@ +package org.fox.ttrss.share; + +import android.app.Activity; +import android.os.Bundle; +import android.util.Log; +import android.view.Display; +import android.widget.Toast; + +public class CommonActivity extends Activity { + private final String TAG = this.getClass().getSimpleName(); + + private boolean m_smallScreenMode = true; + private boolean m_compatMode = false; + + protected void setSmallScreen(boolean smallScreen) { + Log.d(TAG, "m_smallScreenMode=" + smallScreen); + m_smallScreenMode = smallScreen; + } + + public void toast(int msgId) { + Toast toast = Toast.makeText(CommonActivity.this, msgId, Toast.LENGTH_SHORT); + toast.show(); + } + + public void toast(String msg) { + Toast toast = Toast.makeText(CommonActivity.this, msg, Toast.LENGTH_SHORT); + toast.show(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + m_compatMode = android.os.Build.VERSION.SDK_INT <= 10; + + Log.d(TAG, "m_compatMode=" + m_compatMode); + + super.onCreate(savedInstanceState); + } + + public boolean isSmallScreen() { + return m_smallScreenMode; + } + + public boolean isCompatMode() { + return m_compatMode; + } + + public boolean isPortrait() { + Display display = getWindowManager().getDefaultDisplay(); + + int width = display.getWidth(); + int height = display.getHeight(); + + return width < height; + } + + +} diff --git a/src/org/fox/ttrss/share/CommonShareActivity.java b/src/org/fox/ttrss/share/CommonShareActivity.java new file mode 100644 index 00000000..ab90d08c --- /dev/null +++ b/src/org/fox/ttrss/share/CommonShareActivity.java @@ -0,0 +1,186 @@ +package org.fox.ttrss.share; + +import java.util.HashMap; + +import org.fox.ttrss.ApiRequest; +import org.fox.ttrss.PreferencesActivity; +import org.fox.ttrss.R; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; + + +public abstract class CommonShareActivity extends CommonActivity { + protected SharedPreferences m_prefs; + protected String m_sessionId; + protected int m_apiLevel = 0; + + private final String TAG = this.getClass().getSimpleName(); + + @Override + public void onCreate(Bundle savedInstanceState) { + m_prefs = PreferenceManager + .getDefaultSharedPreferences(getApplicationContext()); + + super.onCreate(savedInstanceState); + + if (savedInstanceState != null) { + m_sessionId = savedInstanceState.getString("sessionId"); + m_apiLevel = savedInstanceState.getInt("apiLevel"); + } + } + + @Override + public void onSaveInstanceState(Bundle out) { + super.onSaveInstanceState(out); + + out.putString("sessionId", m_sessionId); + out.putInt("apiLevel", m_apiLevel); + } + + protected abstract void onLoggedIn(int requestId); + + protected abstract void onLoggingIn(int requestId); + + @SuppressWarnings({ "unchecked", "serial" }) + public void login(int requestId) { + + if (m_prefs.getString("ttrss_url", "").trim().length() == 0) { + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage(R.string.dialog_need_configure_prompt) + .setCancelable(false) + .setPositiveButton(R.string.dialog_open_preferences, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // launch preferences + + Intent intent = new Intent(CommonShareActivity.this, + PreferencesActivity.class); + startActivityForResult(intent, 0); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + AlertDialog alert = builder.create(); + alert.show(); + + } else { + + LoginRequest ar = new LoginRequest(getApplicationContext(), requestId); + + HashMap map = new HashMap() { + { + put("op", "login"); + put("user", m_prefs.getString("login", "").trim()); + put("password", m_prefs.getString("password", "").trim()); + } + }; + + onLoggingIn(requestId); + + ar.execute(map); + } + } + + protected class LoginRequest extends ApiRequest { + private int m_requestId; + + public LoginRequest(Context context, int requestId) { + super(context); + m_requestId = requestId; + } + + @SuppressWarnings("unchecked") + protected void onPostExecute(JsonElement result) { + if (result != null) { + try { + JsonObject content = result.getAsJsonObject(); + if (content != null) { + m_sessionId = content.get("session_id").getAsString(); + + Log.d(TAG, "Authenticated!"); + + ApiRequest req = new ApiRequest(m_context) { + protected void onPostExecute(JsonElement result) { + m_apiLevel = 0; + + if (result != null) { + try { + m_apiLevel = result.getAsJsonObject() + .get("level").getAsInt(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + Log.d(TAG, "Received API level: " + m_apiLevel); + + onLoggedIn(m_requestId); + } + }; + + @SuppressWarnings("serial") + HashMap map = new HashMap() { + { + put("sid", m_sessionId); + put("op", "getApiLevel"); + } + }; + + req.execute(map); + + return; + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + m_sessionId = null; + + toast(getErrorMessage()); + setProgressBarIndeterminateVisibility(false); + } + + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.preferences: + Intent intent = new Intent(CommonShareActivity.this, + PreferencesActivity.class); + startActivityForResult(intent, 0); + return true; + default: + Log.d(TAG, + "onOptionsItemSelected, unhandled id=" + item.getItemId()); + return super.onOptionsItemSelected(item); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.share_menu, menu); + return true; + } + + + +} diff --git a/src/org/fox/ttrss/share/FeedCategory.java b/src/org/fox/ttrss/share/FeedCategory.java new file mode 100644 index 00000000..aae1ce62 --- /dev/null +++ b/src/org/fox/ttrss/share/FeedCategory.java @@ -0,0 +1,58 @@ +package org.fox.ttrss.share; + +import android.os.Parcel; +import android.os.Parcelable; + +public class FeedCategory implements Parcelable { + public int id; + public String title; + public int unread; + public int order_id; + + public FeedCategory(Parcel in) { + readFromParcel(in); + } + + public FeedCategory(int id, String title, int unread) { + this.id = id; + this.title = title; + this.unread = unread; + this.order_id = 0; + } + + public FeedCategory() { + + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(id); + out.writeString(title); + out.writeInt(unread); + out.writeInt(order_id); + } + + public void readFromParcel(Parcel in) { + id = in.readInt(); + title = in.readString(); + unread = in.readInt(); + order_id = in.readInt(); + } + + @SuppressWarnings("rawtypes") + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public FeedCategory createFromParcel(Parcel in) { + return new FeedCategory(in); + } + + public FeedCategory[] newArray(int size) { + return new FeedCategory[size]; + } + }; +} diff --git a/src/org/fox/ttrss/share/FeedCategoryList.java b/src/org/fox/ttrss/share/FeedCategoryList.java new file mode 100644 index 00000000..26270b18 --- /dev/null +++ b/src/org/fox/ttrss/share/FeedCategoryList.java @@ -0,0 +1,52 @@ +package org.fox.ttrss.share; + +import java.util.ArrayList; + + +import android.os.Parcel; +import android.os.Parcelable; + +@SuppressWarnings("serial") +public class FeedCategoryList extends ArrayList implements Parcelable { + + public FeedCategoryList() { } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(this.size()); + for (FeedCategory feed : this) { + out.writeParcelable(feed, flags); + } + } + + public void readFromParcel(Parcel in) { + int length = in.readInt(); + + for (int i = 0; i < length; i++) { + FeedCategory feed = in.readParcelable(FeedCategory.class.getClassLoader()); + this.add(feed); + } + + } + + public FeedCategoryList(Parcel in) { + readFromParcel(in); + } + + @SuppressWarnings("rawtypes") + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public FeedCategoryList createFromParcel(Parcel in) { + return new FeedCategoryList(in); + } + + public FeedCategoryList[] newArray(int size) { + return new FeedCategoryList[size]; + } + }; + } diff --git a/src/org/fox/ttrss/share/ShareActivity.java b/src/org/fox/ttrss/share/ShareActivity.java new file mode 100644 index 00000000..8c7bcdf1 --- /dev/null +++ b/src/org/fox/ttrss/share/ShareActivity.java @@ -0,0 +1,146 @@ +package org.fox.ttrss.share; + +import java.util.HashMap; + +import org.fox.ttrss.ApiRequest; +import org.fox.ttrss.R; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.EditText; + +import com.google.gson.JsonElement; + +public class ShareActivity extends CommonShareActivity { + private final String TAG = this.getClass().getSimpleName(); + + private Button m_button; + + @Override + public void onCreate(Bundle savedInstanceState) { + //setTheme(R.style.DarkTheme); + + super.onCreate(savedInstanceState); + + requestWindowFeature(Window.FEATURE_LEFT_ICON); + + Intent intent = getIntent(); + + String urlValue = intent.getStringExtra(Intent.EXTRA_TEXT); + String titleValue = intent.getStringExtra(Intent.EXTRA_SUBJECT); + String contentValue = ""; + + if (savedInstanceState != null) { + urlValue = savedInstanceState.getString("url"); + titleValue = savedInstanceState.getString("title"); + contentValue = savedInstanceState.getString("content"); + } + + setContentView(R.layout.share); + + getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.icon); + + setSmallScreen(false); + + EditText url = (EditText) findViewById(R.id.url); + url.setText(urlValue); + + EditText title = (EditText) findViewById(R.id.title); + title.setText(titleValue); + + EditText content = (EditText) findViewById(R.id.content); + content.setText(contentValue); + + m_button = (Button) findViewById(R.id.share_button); + + m_button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + login(0); + } + }); + } + + @Override + public void onSaveInstanceState(Bundle out) { + super.onSaveInstanceState(out); + + EditText url = (EditText) findViewById(R.id.url); + + if (url != null) { + out.putString("url", url.getText().toString()); + } + + EditText title = (EditText) findViewById(R.id.title); + + if (title != null) { + out.putString("title", title.getText().toString()); + } + + EditText content = (EditText) findViewById(R.id.content); + + if (content != null) { + out.putString("content", content.getText().toString()); + } + + } + + private void postData() { + m_button.setEnabled(false); + + ApiRequest req = new ApiRequest(getApplicationContext()) { + protected void onPostExecute(JsonElement result) { + setProgressBarIndeterminateVisibility(false); + + if (m_lastError != ApiError.NO_ERROR) { + toast(getErrorMessage()); + } else { + toast(R.string.share_article_posted); + finish(); + } + + m_button.setEnabled(true); + } + }; + + final EditText url = (EditText) findViewById(R.id.url); + final EditText title = (EditText) findViewById(R.id.title); + final EditText content = (EditText) findViewById(R.id.content); + + if (url != null && title != null && content != null) { + HashMap map = new HashMap() { + { + put("sid", m_sessionId); + put("op", "shareToPublished"); + put("title", title.getText().toString()); + put("url", url.getText().toString()); + put("content", content.getText().toString()); + } + }; + + setProgressBarIndeterminateVisibility(true); + + req.execute(map); + } + } + + + @Override + public void onLoggingIn(int requestId) { + m_button.setEnabled(false); + } + + @Override + protected void onLoggedIn(int requestId) { + m_button.setEnabled(true); + + if (m_apiLevel < 4) { + toast(R.string.api_too_low); + } else { + postData(); + } + } +} diff --git a/src/org/fox/ttrss/share/SubscribeActivity.java b/src/org/fox/ttrss/share/SubscribeActivity.java new file mode 100644 index 00000000..b69500ef --- /dev/null +++ b/src/org/fox/ttrss/share/SubscribeActivity.java @@ -0,0 +1,275 @@ +package org.fox.ttrss.share; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.fox.ttrss.ApiRequest; +import org.fox.ttrss.ApiRequest.ApiError; +import org.fox.ttrss.R; + +import android.content.Context; +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Spinner; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.reflect.TypeToken; + +public class SubscribeActivity extends CommonShareActivity { + private final String TAG = this.getClass().getSimpleName(); + + private Button m_postButton; + private Button m_catButton; + private CatListAdapter m_adapter; + private FeedCategoryList m_cats = new FeedCategoryList(); + + private static final int REQ_CATS = 1; + private static final int REQ_POST = 2; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + requestWindowFeature(Window.FEATURE_LEFT_ICON); + + String urlValue = getIntent().getDataString(); + + if (savedInstanceState != null) { + urlValue = savedInstanceState.getString("url"); + + ArrayList list = savedInstanceState.getParcelableArrayList("cats"); + + for (FeedCategory c : list) + m_cats.add(c); + } + + setContentView(R.layout.subscribe); + + getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.icon); + + setSmallScreen(false); + + Spinner catList = (Spinner) findViewById(R.id.category_spinner); + + if (m_cats.size() == 0) m_cats.add(new FeedCategory(0, "Uncategorized", 0)); + + m_adapter = new CatListAdapter(this, android.R.layout.simple_spinner_dropdown_item, m_cats); + catList.setAdapter(m_adapter); + + EditText feedUrl = (EditText) findViewById(R.id.feed_url); + feedUrl.setText(urlValue); + + m_postButton = (Button) findViewById(R.id.subscribe_button); + + m_postButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + login(REQ_POST); + } + }); + + m_catButton = (Button) findViewById(R.id.cats_button); + + m_catButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + login(REQ_CATS); + } + }); + + login(REQ_CATS); + } + + @Override + public void onSaveInstanceState(Bundle out) { + super.onSaveInstanceState(out); + + EditText url = (EditText) findViewById(R.id.url); + + if (url != null) { + out.putString("url", url.getText().toString()); + } + + out.putParcelableArrayList("cats", m_cats); + + } + + private void subscribeToFeed() { + m_postButton.setEnabled(false); + + ApiRequest req = new ApiRequest(getApplicationContext()) { + protected void onPostExecute(JsonElement result) { + setProgressBarIndeterminateVisibility(false); + + if (m_lastError != ApiError.NO_ERROR) { + toast(getErrorMessage()); + } else { + try { + switch (m_apiStatusCode) { + case 0: + toast(R.string.error_feed_already_exists_); + finish(); + break; + case 1: + toast(R.string.subscribed_to_feed); + finish(); + break; + case 2: + toast(R.string.error_invalid_url); + break; + case 3: + toast(R.string.error_url_is_an_html_page_no_feeds_found); + break; + case 4: + toast(R.string.error_url_contains_multiple_feeds); + break; + case 5: + toast(R.string.error_could_not_download_url); + break; + } + + } catch (Exception e) { + toast(R.string.error_while_subscribing); + e.printStackTrace(); + } + } + + m_postButton.setEnabled(true); + } + }; + + Spinner catSpinner = (Spinner) findViewById(R.id.category_spinner); + + final FeedCategory cat = (FeedCategory) m_adapter.getCategory(catSpinner.getSelectedItemPosition()); + final EditText feedUrl = (EditText) findViewById(R.id.feed_url); + + if (feedUrl != null ) { + HashMap map = new HashMap() { + { + put("sid", m_sessionId); + put("op", "subscribeToFeed"); + put("feed_url", feedUrl.getText().toString()); + + if (cat != null) { + put("category_id", String.valueOf(cat.id)); + } + } + }; + + setProgressBarIndeterminateVisibility(true); + + req.execute(map); + } + } + + @Override + public void onLoggingIn(int requestId) { + switch (requestId) { + case REQ_CATS: + m_catButton.setEnabled(false); + break; + case REQ_POST: + m_postButton.setEnabled(false); + break; + } + } + + private void updateCats() { + ApiRequest req = new ApiRequest(getApplicationContext()) { + protected void onPostExecute(JsonElement result) { + setProgressBarIndeterminateVisibility(false); + + if (m_lastError != ApiError.NO_ERROR) { + toast(getErrorMessage()); + } else { + JsonArray content = result.getAsJsonArray(); + + if (content != null) { + Type listType = new TypeToken>() {}.getType(); + final List cats = new Gson().fromJson(content, listType); + + m_cats.clear(); + m_cats.add(new FeedCategory(0, "Uncategorized", 0)); + + for (FeedCategory c : cats) { + if (c.id > 0) + m_cats.add(c); + } + + m_adapter.notifyDataSetChanged(); + + toast(R.string.category_list_updated); + } + } + + m_catButton.setEnabled(true); + } + }; + + HashMap map = new HashMap() { + { + put("sid", m_sessionId); + put("op", "getCategories"); + } + }; + + setProgressBarIndeterminateVisibility(true); + + req.execute(map); + } + + @Override + protected void onLoggedIn(int requestId) { + switch (requestId) { + case REQ_CATS: + updateCats(); + break; + case REQ_POST: + m_postButton.setEnabled(true); + if (m_apiLevel < 5) { + toast(R.string.api_too_low); + } else { + subscribeToFeed(); + } + break; + } + } + + private class CatListAdapter extends ArrayAdapter { + private List m_items; + + public CatListAdapter(Context context, int resource, + List items) { + super(context, resource); + + m_items = items; + } + + @Override + public String getItem(int item) { + return m_items.get(item).title; + } + + public FeedCategory getCategory(int item) { + try { + return m_items.get(item); + } catch (ArrayIndexOutOfBoundsException e) { + return null; + } + } + + @Override + public int getCount() { + return m_items.size(); + } + } + +} -- cgit v1.2.3-54-g00ecf