summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2013-03-24 19:43:03 +0400
committerAndrew Dolgov <[email protected]>2013-03-24 19:43:03 +0400
commitad12b2b945d23af48d3930c1602971dc8e4924d8 (patch)
tree3c35724d3f9ce0faf9989a12e6ae021f9bef899c
parentc6493ebb707216fcc5241528298b94302c49d373 (diff)
integrate share app stuff into tt-rss app
-rw-r--r--AndroidManifest.xml129
-rw-r--r--res/layout/share.xml53
-rw-r--r--res/layout/subscribe.xml51
-rw-r--r--res/menu/main_menu.xml6
-rw-r--r--res/menu/share_menu.xml9
-rw-r--r--res/values-v11/style.xml3
-rw-r--r--res/values-v15/style.xml3
-rw-r--r--res/values/strings.xml84
-rw-r--r--res/values/style.xml2
-rw-r--r--src/org/fox/ttrss/OnlineActivity.java6
-rw-r--r--src/org/fox/ttrss/share/CommonActivity.java57
-rw-r--r--src/org/fox/ttrss/share/CommonShareActivity.java186
-rw-r--r--src/org/fox/ttrss/share/FeedCategory.java58
-rw-r--r--src/org/fox/ttrss/share/FeedCategoryList.java52
-rw-r--r--src/org/fox/ttrss/share/ShareActivity.java146
-rw-r--r--src/org/fox/ttrss/share/SubscribeActivity.java275
16 files changed, 1078 insertions, 42 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4bad3740..b45a2850 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.fox.ttrss"
- android:versionCode="146"
- android:versionName="1.23" >
+ android:versionCode="147"
+ android:versionName="1.3" >
<uses-sdk
android:minSdkVersion="8"
@@ -32,42 +32,151 @@
android:name=".PreferencesActivity"
android:label="@string/preferences" >
</activity>
-
<activity
android:name=".FeedsActivity"
android:label="@string/app_name" >
</activity>
-
<activity
android:name=".HeadlinesActivity"
android:label="@string/app_name" >
</activity>
-
<activity
android:name=".CommonActivity"
android:label="@string/app_name" >
</activity>
-
<activity
android:name=".ArticleActivity"
android:label="@string/app_name" >
</activity>
-
<activity
android:name=".offline.OfflineActivity"
android:label="@string/app_name" >
</activity>
-
<activity
android:name=".offline.OfflineFeedsActivity"
android:label="@string/app_name" >
</activity>
-
<activity
android:name=".offline.OfflineHeadlinesActivity"
android:label="@string/app_name" >
</activity>
-
+ <activity
+ android:name=".share.ShareActivity"
+ android:excludeFromRecents="true"
+ android:label="@string/app_name"
+ android:theme="@style/DarkDialogTheme" >
+ <intent-filter>
+ <action android:name="android.intent.action.SEND" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+
+ <data android:mimeType="text/plain" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".share.SubscribeActivity"
+ android:excludeFromRecents="true"
+ android:label="@string/subscribe_name"
+ android:theme="@style/DarkDialogTheme" >
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.BROWSABLE" />
+ <category android:name="android.intent.category.DEFAULT" />
+
+ <data android:scheme="itpc" />
+ <data android:scheme="pcast" />
+ <data android:scheme="feed" />
+ <data android:scheme="rss" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data
+ android:host="*"
+ android:pathPattern=".*xml"
+ android:scheme="http" />
+ <data
+ android:host="*"
+ android:pathPattern=".*rss"
+ android:scheme="http" />
+ <data
+ android:host="*"
+ android:pathPattern=".*feed.*"
+ android:scheme="http" />
+ <data
+ android:host="*"
+ android:pathPattern=".*podcast.*"
+ android:scheme="http" />
+ <data
+ android:host="*"
+ android:pathPattern=".*Podcast.*"
+ android:scheme="http" />
+ <data
+ android:host="*"
+ android:pathPattern=".*rss.*"
+ android:scheme="http" />
+ <data
+ android:host="*"
+ android:pathPattern=".*RSS.*"
+ android:scheme="http" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data
+ android:mimeType="text/xml"
+ android:scheme="http" />
+ <data
+ android:mimeType="application/rss+xml"
+ android:scheme="http" />
+ <data
+ android:mimeType="application/atom+xml"
+ android:scheme="http" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data android:scheme="http" />
+ <data android:host="*" />
+ <data android:pathPattern=".*\\.xml" />
+ <data android:pathPattern=".*\\.rss" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data android:scheme="http" />
+ <data android:host="feeds.feedburner.com" />
+ <data android:host="feedproxy.google.com" />
+ <data android:host="feeds2.feedburner.com" />
+ <data android:host="feedsproxy.google.com" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data android:scheme="http" />
+ <data android:mimeType="text/xml" />
+ <data android:mimeType="application/rss+xml" />
+ <data android:mimeType="application/atom+xml" />
+ <data android:mimeType="application/xml" />
+ </intent-filter>
+ </activity>
+
<service
android:name=".offline.OfflineDownloadService"
android:enabled="true" />
diff --git a/res/layout/share.xml b/res/layout/share.xml
new file mode 100644
index 00000000..f1803130
--- /dev/null
+++ b/res/layout/share.xml
@@ -0,0 +1,53 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="5dp" >
+
+ <EditText
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:ems="10"
+ android:hint="@string/share_title_hint"
+ android:singleLine="true" />
+
+ <EditText
+ android:id="@+id/url"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@+id/title"
+ android:layout_alignParentRight="true"
+ android:layout_below="@+id/title"
+ android:ems="10"
+ android:hint="@string/share_url_hint"
+ android:singleLine="true" />
+
+ <EditText
+ android:id="@+id/content"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignRight="@+id/url"
+ android:layout_below="@+id/url"
+ android:ems="10"
+ android:hint="@string/share_content_hint"
+ android:inputType="textMultiLine"
+ android:maxLines="3" >
+
+ <requestFocus />
+ </EditText>
+
+ <Button
+ android:id="@+id/share_button"
+ android:layout_width="100dp"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignRight="@+id/content"
+ android:layout_below="@+id/content"
+ android:text="@string/share_share_button" />
+
+</RelativeLayout> \ No newline at end of file
diff --git a/res/layout/subscribe.xml b/res/layout/subscribe.xml
new file mode 100644
index 00000000..3b61424a
--- /dev/null
+++ b/res/layout/subscribe.xml
@@ -0,0 +1,51 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="5dp" >
+
+ <EditText
+ android:id="@+id/feed_url"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentRight="true"
+ android:ems="10"
+ android:hint="@string/feed_url"
+ android:inputType="textUri"
+ android:maxLines="3" >
+
+ <requestFocus />
+ </EditText>
+
+ <Spinner
+ android:id="@+id/category_spinner"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@+id/feed_url"
+ android:layout_alignParentRight="true"
+ android:layout_below="@+id/feed_url" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@+id/category_spinner"
+ android:layout_alignRight="@+id/category_spinner"
+ android:layout_below="@+id/category_spinner" >
+
+ <Button
+ android:id="@+id/cats_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0.5"
+ android:text="Update categories" />
+
+ <Button
+ android:id="@+id/subscribe_button"
+ android:layout_width="wrap_content"
+ android:layout_weight="0.5"
+ android:layout_height="wrap_content"
+ android:text="@string/subscribe_to_feed" />
+ </LinearLayout>
+
+</RelativeLayout> \ No newline at end of file
diff --git a/res/menu/main_menu.xml b/res/menu/main_menu.xml
index f5ccb879..aef776cc 100644
--- a/res/menu/main_menu.xml
+++ b/res/menu/main_menu.xml
@@ -12,6 +12,12 @@
-->
<item
+ android:id="@+id/subscribe_to_feed"
+ android:icon="@android:drawable/ic_menu_add"
+ android:showAsAction=""
+ android:title="Subscribe to feed"/>
+
+ <item
android:id="@+id/show_feeds"
android:icon="@android:drawable/ic_menu_agenda"
android:showAsAction=""
diff --git a/res/menu/share_menu.xml b/res/menu/share_menu.xml
new file mode 100644
index 00000000..7eb79800
--- /dev/null
+++ b/res/menu/share_menu.xml
@@ -0,0 +1,9 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/preferences"
+ android:icon="@android:drawable/ic_menu_preferences"
+ android:showAsAction=""
+ android:title="@string/preferences"/>
+
+</menu> \ No newline at end of file
diff --git a/res/values-v11/style.xml b/res/values-v11/style.xml
index c1da4b43..918b1642 100644
--- a/res/values-v11/style.xml
+++ b/res/values-v11/style.xml
@@ -88,4 +88,7 @@
<item name="android:background">#232527</item>
</style>
+ <style name="DarkDialogTheme" parent="android:Theme.Holo.Dialog">
+ </style>
+
</resources> \ No newline at end of file
diff --git a/res/values-v15/style.xml b/res/values-v15/style.xml
index 52e16a18..b3bd7860 100644
--- a/res/values-v15/style.xml
+++ b/res/values-v15/style.xml
@@ -92,4 +92,7 @@
<item name="android:background">#232527</item>
</style>
+ <style name="DarkDialogTheme" parent="android:Theme.Holo.Dialog">
+ </style>
+
</resources> \ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f21ef831..18d50121 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -74,33 +74,33 @@
<string name="error_api_incorrect_usage">Error: incorrect API usage</string>
<string name="error_login_failed">Error: username or password incorrect</string>
<string name="error_invalid_api_url">Error: invalid API URL</string>
- <string name="combined_mode_summary">Displays full article text inline, instead of a separate panel</string>
- <string name="combined_mode">Combined mode</string>
- <string name="go_offline">Go offline</string>
- <string name="go_online">Go online</string>
- <string name="offline_switch_error">Failed to prepare offline mode (see log)</string>
- <string name="no_feeds">No feeds to display</string>
- <string name="no_headlines">No articles to display</string>
- <string name="dialog_offline_prompt">Login failed, but you have stored offline data. Would you like to go offline?</string>
- <string name="dialog_offline_success">Offline mode is ready</string>
- <string name="dialog_offline_go">Go offline</string>
- <string name="dialog_cancel">Cancel</string>
- <string name="dialog_offline_switch_prompt">Download unread articles and go offline?</string>
- <string name="notify_downloading_articles">Downloading articles (%1$d)…</string>
- <string name="notify_downloading_init">Starting download…</string>
- <string name="notify_downloading_feeds">Downloading feeds…</string>
- <string name="notify_uploading_sending_data">Sending data to server…</string>
- <string name="notify_downloading_title">Preparing offline mode</string>
- <string name="notify_uploading_title">Synchronizing offline data</string>
- <string name="offline_sync_success">Finished synchronizing your offline data</string>
- <string name="offline_mode">Offline mode</string>
- <string name="offline_image_cache_enabled">Cache images</string>
- <string name="offline_image_cache_enabled_summary">Download images to sdcard. This might significantly increase time it takes to go offline.</string>
- <string name="notify_downloading_images">Downloading images (%1$d)…</string>
- <string name="article_set_labels">Set labels</string>
- <string name="search">Search</string>
- <string name="cancel">Cancel</string>
- <string name="font_size_small">Small</string>
+ <string name="combined_mode_summary">Displays full article text inline, instead of a separate panel</string>
+ <string name="combined_mode">Combined mode</string>
+ <string name="go_offline">Go offline</string>
+ <string name="go_online">Go online</string>
+ <string name="offline_switch_error">Failed to prepare offline mode (see log)</string>
+ <string name="no_feeds">No feeds to display</string>
+ <string name="no_headlines">No articles to display</string>
+ <string name="dialog_offline_prompt">Login failed, but you have stored offline data. Would you like to go offline?</string>
+ <string name="dialog_offline_success">Offline mode is ready</string>
+ <string name="dialog_offline_go">Go offline</string>
+ <string name="dialog_cancel">Cancel</string>
+ <string name="dialog_offline_switch_prompt">Download unread articles and go offline?</string>
+ <string name="notify_downloading_articles">Downloading articles (%1$d)…</string>
+ <string name="notify_downloading_init">Starting download…</string>
+ <string name="notify_downloading_feeds">Downloading feeds…</string>
+ <string name="notify_uploading_sending_data">Sending data to server…</string>
+ <string name="notify_downloading_title">Preparing offline mode</string>
+ <string name="notify_uploading_title">Synchronizing offline data</string>
+ <string name="offline_sync_success">Finished synchronizing your offline data</string>
+ <string name="offline_mode">Offline mode</string>
+ <string name="offline_image_cache_enabled">Cache images</string>
+ <string name="offline_image_cache_enabled_summary">Download images to sdcard. This might significantly increase time it takes to go offline.</string>
+ <string name="notify_downloading_images">Downloading images (%1$d)…</string>
+ <string name="article_set_labels">Set labels</string>
+ <string name="search">Search</string>
+ <string name="cancel">Cancel</string>
+ <string name="font_size_small">Small</string>
<string name="font_size_medium">Medium</string>
<string name="font_size_large">Large</string>
<string name="pref_font_size">Article text size</string>
@@ -156,8 +156,28 @@
<string name="prefs_fullscreen_mode">Fullscreen mode</string>
<string name="reading">Reading</string>
<string name="theme_dark_gray">Dark gray</string>
- <string name="offline_articles_to_download">Number of articles to download</string>
- <string name="offline_articles_to_download_long">Number of articles to download for Offlinemode. (newest first)</string>
- <string name="pref_headlines_show_content_long">Show content previews in headlines list</string>
- <string name="pref_headlines_show_content">Preview article content</string>
-</resources>
+ <string name="offline_articles_to_download">Number of articles to download</string>
+ <string name="offline_articles_to_download_long">Number of articles to download for Offlinemode. (newest first)</string>
+ <string name="pref_headlines_show_content_long">Show content previews in headlines list</string>
+ <string name="pref_headlines_show_content">Preview article content</string>
+ <string name="api_too_low">This action requires newer version of Tiny Tiny RSS</string>
+ <string name="share_url_prompt">URL:</string>
+ <string name="share_url_hint">Article URL</string>
+ <string name="share_content_hint">Article Content</string>
+ <string name="share_title_prompt">Title:</string>
+ <string name="share_title_hint">Article Title</string>
+ <string name="share_share_button">Share</string>
+ <string name="share_article_posted">Article posted.</string>
+ <string name="subscribe_name">Subscribe with Tiny Tiny RSS</string>
+ <string name="feed_url">Feed URL</string>
+ <string name="subscribe_to_feed">Subscribe to feed</string>
+ <string name="error_while_subscribing">Error while subscribing.</string>
+ <string name="category_list_updated">Category list updated</string>
+ <string name="subscribed_to_feed">Subscribed to feed</string>
+ <string name="error_feed_already_exists_">Error: feed already exists.</string>
+ <string name="error_invalid_url">Error: Invalid URL.</string>
+ <string name="error_url_is_an_html_page_no_feeds_found">Error: URL is an HTML page, no feeds found.</string>
+ <string name="error_url_contains_multiple_feeds">Error: URL contains multiple feeds</string>
+ <string name="error_could_not_download_url">Error: Could not download URL</string>
+
+</resources> \ No newline at end of file
diff --git a/res/values/style.xml b/res/values/style.xml
index a817f33b..c8bd7207 100644
--- a/res/values/style.xml
+++ b/res/values/style.xml
@@ -84,5 +84,7 @@
<item name="android:actionBarStyle">@style/ActionBarDarkGray</item>
</style>
+ <style name="DarkDialogTheme" parent="android:Theme.Dialog">
+ </style>
</resources> \ No newline at end of file
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<String, String> map = new HashMap<String, String>() {
+ {
+ 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<String, String> map = new HashMap<String, String>() {
+ {
+ 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<FeedCategory> 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<String, String> map = new HashMap<String, String>() {
+ {
+ 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<FeedCategory> 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<String, String> map = new HashMap<String, String>() {
+ {
+ 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<List<FeedCategory>>() {}.getType();
+ final List<FeedCategory> 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<String, String> map = new HashMap<String, String>() {
+ {
+ 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<String> {
+ private List<FeedCategory> m_items;
+
+ public CatListAdapter(Context context, int resource,
+ List<FeedCategory> 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();
+ }
+ }
+
+}