summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2011-11-29 20:00:37 +0300
committerAndrew Dolgov <[email protected]>2011-11-29 20:00:37 +0300
commit574aaebb900b8420b3adcf05a7bc971c002ed327 (patch)
tree3469e51b9ec9da7fbf75c6e2464edb26992c5639
parenta36e2e8d0c9496ecefb5cc1ed525932c7a5f77d1 (diff)
properly use context menu for operations on selected headlines
-rw-r--r--res/menu/headlines_menu.xml21
-rw-r--r--res/menu/main_menu.xml29
-rw-r--r--res/values/strings.xml13
-rw-r--r--src/org/fox/ttrss/FeedCategoriesFragment.java42
-rw-r--r--src/org/fox/ttrss/FeedsFragment.java37
-rw-r--r--src/org/fox/ttrss/HeadlinesFragment.java34
-rw-r--r--src/org/fox/ttrss/MainActivity.java177
7 files changed, 237 insertions, 116 deletions
diff --git a/res/menu/headlines_menu.xml b/res/menu/headlines_menu.xml
new file mode 100644
index 00000000..ac614810
--- /dev/null
+++ b/res/menu/headlines_menu.xml
@@ -0,0 +1,21 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/selection_toggle_unread"
+ android:icon="@android:drawable/ic_menu_recent_history"
+ android:showAsAction=""
+ android:title="@string/selection_toggle_unread"/>
+
+ <item
+ android:id="@+id/selection_toggle_marked"
+ android:icon="@android:drawable/star_off"
+ android:showAsAction=""
+ android:title="@string/selection_toggle_marked"/>
+
+ <item
+ android:id="@+id/selection_toggle_published"
+ android:icon="@drawable/ic_menu_rss"
+ android:showAsAction=""
+ android:title="@string/selection_toggle_published"/>
+
+</menu> \ No newline at end of file
diff --git a/res/menu/main_menu.xml b/res/menu/main_menu.xml
index a23bcb61..2d2e2998 100644
--- a/res/menu/main_menu.xml
+++ b/res/menu/main_menu.xml
@@ -38,11 +38,18 @@
android:title="@string/load_more_articles"/>
<item
+ android:id="@+id/catchup_and_load"
+ android:icon="@android:drawable/ic_menu_rotate"
+ android:showAsAction="ifRoom|withText"
+ android:title="@string/catchup_and_load"/>
+
+ <item
android:id="@+id/show_all_articles"
android:icon="@android:drawable/ic_menu_agenda"
android:showAsAction=""
android:title="@string/show_all_articles"/>
+
<item
android:id="@+id/headlines_select_all"
android:title="@string/headlines_select_all"/>
@@ -50,30 +57,10 @@
<item
android:id="@+id/headlines_select_unread"
android:title="@string/headlines_select_unread"/>
-
+
<item
android:id="@+id/headlines_select_none"
android:title="@string/headlines_select_none"/>
-
- <item
- android:id="@+id/selection_toggle_unread"
- android:icon="@android:drawable/ic_menu_recent_history"
- android:showAsAction=""
- android:title="@string/selection_toggle_unread"/>
-
- <item
- android:id="@+id/selection_toggle_marked"
- android:icon="@android:drawable/star_off"
- android:showAsAction=""
- android:title="@string/selection_toggle_marked"/>
-
- <item
- android:id="@+id/selection_toggle_published"
- android:icon="@drawable/ic_menu_rss"
- android:showAsAction=""
- android:title="@string/selection_toggle_published"/>
-
-
</group>
<group android:id="@+id/menu_group_article" >
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8c80ddcf..853f9036 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -22,6 +22,8 @@
<string name="preferences">Preferences</string>
<string name="theme_light">Light</string>
<string name="connection">Connection</string>
+ <string name="headline_context_multiple">Selection toggle</string>
+ <string name="headline_context_single">Article toggle</string>
<string name="http_authentication">HTTP Authentication</string>
<string name="login_success">Logged in.</string>
<string name="no_unread_feeds">No unread feeds.</string>
@@ -34,7 +36,7 @@
<string name="share_article">Share article</string>
<string name="catchup">Mark as read</string>
<string name="sort_feeds_by_unread">Sort feeds by unread count</string>
- <string name="load_more_articles">Load more...</string>
+ <string name="load_more_articles">Load more</string>
<string name="show_all_articles">Show all articles</string>
<string name="show_unread_articles">Show unread articles</string>
<string name="ssl_trust_any">Accept any SSL certificate</string>
@@ -46,10 +48,10 @@
<string name="toggle_published">Toggle published</string>
<string name="headlines_select_all">Select all</string>
<string name="headlines_select_none">Select none</string>
- <string name="headlines_select_unread">Select unread</string>
- <string name="selection_toggle_marked">Toggle starred</string>
- <string name="selection_toggle_published">Toggle published</string>
- <string name="selection_toggle_unread">Toggle unread</string>
+ <string name="headlines_select_unread">Unread</string>
+ <string name="selection_toggle_marked">Starred</string>
+ <string name="selection_toggle_published">Published</string>
+ <string name="selection_toggle_unread">Unread</string>
<string name="set_unread">Mark unread</string>
<string name="http_login_summary">Optional. Fill this if your tt-rss installation is protected by HTTP Basic authentication</string>
<string name="login_summary">Your tt-rss login. Not needed for single user mode</string>
@@ -63,6 +65,7 @@
<string name="no_headlines_to_display">No headlines to display</string>
<string name="browse_cats_like_feeds">Browse categories like feeds</string>
<string name="browse_cats_like_feeds_summary">You can long-tap on a category to override this setting</string>
+ <string name="catchup_and_load">Catchup</string>
<string name="error_no_error">No error</string>
<string name="error_unknown">Error: Unknown error (see log)</string>
diff --git a/src/org/fox/ttrss/FeedCategoriesFragment.java b/src/org/fox/ttrss/FeedCategoriesFragment.java
index a607403c..100826c4 100644
--- a/src/org/fox/ttrss/FeedCategoriesFragment.java
+++ b/src/org/fox/ttrss/FeedCategoriesFragment.java
@@ -75,38 +75,19 @@ public class FeedCategoriesFragment extends Fragment implements OnItemClickListe
ContextMenuInfo menuInfo) {
getActivity().getMenuInflater().inflate(R.menu.category_menu, menu);
+
+ AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
+ FeedCategory cat = m_adapter.getItem(info.position);
+
+ if (cat != null)
+ menu.setHeaderTitle(cat.title);
+
super.onCreateContextMenu(menu, v, menuInfo);
}
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
- FeedCategory cat = m_adapter.getItem(info.position);
-
- Log.d(TAG, "onContextItemSelected=" + cat);
-
- MainActivity activity = (MainActivity)getActivity();
-
- if (cat != null) {
- switch (item.getItemId()) {
- case R.id.browse_articles:
- m_selectedCatId = cat.id;
- m_adapter.notifyDataSetChanged();
- activity.viewCategory(cat, true);
- break;
- case R.id.browse_feeds:
- m_selectedCatId = cat.id;
- m_adapter.notifyDataSetChanged();
- activity.viewCategory(cat, false);
- break;
- case R.id.catchup_category:
- activity.catchupFeed(new Feed(cat.id, cat.title, true));
- break;
- }
- }
-
- return true;
+ public FeedCategory getCategoryAtPosition(int position) {
+ return m_adapter.getItem(position);
}
@Override
@@ -358,4 +339,9 @@ public class FeedCategoriesFragment extends Fragment implements OnItemClickListe
m_adapter.notifyDataSetChanged();
}
}
+
+ public void setSelectedCategory(FeedCategory cat) {
+ m_selectedCatId = cat.id;
+ m_adapter.notifyDataSetChanged();
+ }
}
diff --git a/src/org/fox/ttrss/FeedsFragment.java b/src/org/fox/ttrss/FeedsFragment.java
index cec324ab..f3ace4fa 100644
--- a/src/org/fox/ttrss/FeedsFragment.java
+++ b/src/org/fox/ttrss/FeedsFragment.java
@@ -101,32 +101,18 @@ public class FeedsFragment extends Fragment implements OnItemClickListener, OnSh
ContextMenuInfo menuInfo) {
getActivity().getMenuInflater().inflate(R.menu.feed_menu, menu);
+
+ AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
+ Feed feed = m_adapter.getItem(info.position);
+
+ if (feed != null)
+ menu.setHeaderTitle(feed.title);
+
super.onCreateContextMenu(menu, v, menuInfo);
}
@Override
- public boolean onContextItemSelected(MenuItem item) {
- AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
- Feed feed = m_adapter.getItem(info.position);
-
- MainActivity activity = (MainActivity)getActivity();
-
- Log.d(TAG, "onContextItemSelected=" + feed);
-
- if (feed != null) {
- switch (item.getItemId()) {
- case R.id.catchup_feed:
- activity.catchupFeed(feed);
- break;
- }
- }
-
- return true;
- }
-
-
- @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (savedInstanceState != null) {
@@ -141,10 +127,7 @@ public class FeedsFragment extends Fragment implements OnItemClickListener, OnSh
list.setAdapter(m_adapter);
list.setOnItemClickListener(this);
- // http://code.google.com/p/android/issues/detail?id=20065
- // categories fragment is displayed first, so it hogs the context menu events. thanks, google!
- if (!m_prefs.getBoolean("enable_cats", false))
- registerForContextMenu(list);
+ registerForContextMenu(list);
m_enableFeedIcons = m_prefs.getBoolean("download_feed_icons", false);
@@ -556,4 +539,8 @@ public class FeedsFragment extends Fragment implements OnItemClickListener, OnSh
m_enableFeedIcons = m_prefs.getBoolean("download_feed_icons", false);
}
+
+ public Feed getFeedAtPosition(int position) {
+ return m_adapter.getItem(position);
+ }
}
diff --git a/src/org/fox/ttrss/HeadlinesFragment.java b/src/org/fox/ttrss/HeadlinesFragment.java
index c717dca8..59c0e5f1 100644
--- a/src/org/fox/ttrss/HeadlinesFragment.java
+++ b/src/org/fox/ttrss/HeadlinesFragment.java
@@ -17,11 +17,14 @@ import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Html;
import android.util.Log;
+import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
+import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
@@ -53,6 +56,22 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
}
@Override
+ public void onCreateContextMenu(ContextMenu menu, View v,
+ ContextMenuInfo menuInfo) {
+
+ getActivity().getMenuInflater().inflate(R.menu.headlines_menu, menu);
+
+ if (m_selectedArticles.size() > 0) {
+ menu.setHeaderTitle(R.string.headline_context_multiple);
+ } else {
+ menu.setHeaderTitle(R.string.headline_context_single);
+ }
+
+ super.onCreateContextMenu(menu, v, menuInfo);
+
+ }
+
+ @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (savedInstanceState != null) {
@@ -68,6 +87,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
m_adapter = new ArticleListAdapter(getActivity(), R.layout.headlines_row, (ArrayList<Article>)m_articles);
list.setAdapter(m_adapter);
list.setOnItemClickListener(this);
+ registerForContextMenu(list);
Log.d(TAG, "onCreateView, feed=" + m_feed);
@@ -194,7 +214,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
ListView list = (ListView)getView().findViewById(R.id.headlines);
if (list != null && m_offset != 0) {
- list.setSelection(last_position+1);
+ list.setSelection(last_position-1);
}
MainActivity activity = (MainActivity)getActivity();
@@ -403,4 +423,16 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
m_adapter.notifyDataSetChanged();
}
+ public Article getArticleAtPosition(int position) {
+ return m_adapter.getItem(position);
+ }
+
+ public ArticleList getUnreadArticles() {
+ ArticleList tmp = new ArticleList();
+ for (Article a : m_articles) {
+ if (a.unread) tmp.add(a);
+ }
+ return tmp;
+ }
+
}
diff --git a/src/org/fox/ttrss/MainActivity.java b/src/org/fox/ttrss/MainActivity.java
index 929fba41..7aba8cc7 100644
--- a/src/org/fox/ttrss/MainActivity.java
+++ b/src/org/fox/ttrss/MainActivity.java
@@ -22,6 +22,7 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.AnimationUtils;
+import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -524,6 +525,7 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe
refreshCategories();
}
+ @SuppressWarnings("unchecked")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
HeadlinesFragment hf = (HeadlinesFragment)getSupportFragmentManager().findFragmentById(R.id.headlines_fragment);
@@ -560,43 +562,35 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe
case R.id.headlines_select_unread:
if (hf != null) hf.setSelection(HeadlinesFragment.ArticlesSelection.UNREAD);
return true;
- case R.id.selection_toggle_marked:
- if (hf != null) {
- ArticleList selected = hf.getSelectedArticles();
-
- if (selected.size() > 0) {
- for (Article a : selected)
- a.marked = !a.marked;
-
- toggleArticlesMarked(selected);
- hf.notifyUpdated();
- }
- }
- return true;
- case R.id.selection_toggle_published:
+ case R.id.catchup_and_load:
if (hf != null) {
- ArticleList selected = hf.getSelectedArticles();
-
- if (selected.size() > 0) {
- for (Article a : selected)
- a.published = !a.published;
-
- toggleArticlesPublished(selected);
- hf.notifyUpdated();
- }
- }
- return true;
- case R.id.selection_toggle_unread:
- if (hf != null) {
- ArticleList selected = hf.getSelectedArticles();
+ final ArticleList articles = hf.getUnreadArticles();
- if (selected.size() > 0) {
- for (Article a : selected)
- a.unread = !a.unread;
-
- toggleArticlesUnread(selected);
- hf.notifyUpdated();
- }
+ ApiRequest req = new ApiRequest(getApplicationContext()) {
+ @Override
+ protected void onPostExecute(JsonElement result) {
+ if (result != null) {
+ for (Article a : articles)
+ a.unread = false;
+
+ viewFeed(m_activeFeed, true);
+ }
+ }
+ };
+
+ @SuppressWarnings("serial")
+ HashMap<String,String> map = new HashMap<String,String>() {
+ {
+ put("sid", m_sessionId);
+ put("op", "updateArticle");
+ put("article_ids", articlesToIdString(articles));
+ put("mode", "0");
+ put("field", "2");
+ }
+ };
+
+ req.execute(map);
+
}
return true;
case R.id.load_more_articles:
@@ -650,7 +644,7 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe
return super.onOptionsItemSelected(item);
}
}
-
+
public void shareArticle(Article article) {
if (article != null) {
Intent intent = new Intent(Intent.ACTION_SEND);
@@ -1070,6 +1064,117 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe
setLoadingStatus(R.string.login_in_progress, true);
}
}
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
+
+ Log.d(TAG, "onContextItemSelected=" + item.getItemId());
+
+ HeadlinesFragment hf = (HeadlinesFragment)getSupportFragmentManager().findFragmentById(R.id.headlines_fragment);
+ FeedsFragment ff = (FeedsFragment)getSupportFragmentManager().findFragmentById(R.id.feeds_fragment);
+ FeedCategoriesFragment cf = (FeedCategoriesFragment)getSupportFragmentManager().findFragmentById(R.id.cats_fragment);
+
+ switch (item.getItemId()) {
+ case R.id.browse_articles:
+ if (cf != null) {
+ FeedCategory cat = cf.getCategoryAtPosition(info.position);
+ if (cat != null) {
+ viewCategory(cat, true);
+ cf.setSelectedCategory(cat);
+ }
+ }
+ break;
+ case R.id.browse_feeds:
+ if (cf != null) {
+ FeedCategory cat = cf.getCategoryAtPosition(info.position);
+ if (cat != null) {
+ viewCategory(cat, false);
+ cf.setSelectedCategory(cat);
+ }
+ }
+ break;
+ case R.id.catchup_category:
+ if (cf != null) {
+ FeedCategory cat = cf.getCategoryAtPosition(info.position);
+ if (cat != null) {
+ catchupFeed(new Feed(cat.id, cat.title, true));
+ }
+ }
+ break;
+ case R.id.catchup_feed:
+ if (ff != null) {
+ Feed feed = ff.getFeedAtPosition(info.position);
+ if (feed != null) {
+ catchupFeed(feed);
+ }
+ }
+ break;
+ case R.id.selection_toggle_marked:
+ if (hf != null) {
+ ArticleList selected = hf.getSelectedArticles();
+
+ if (selected.size() > 0) {
+ for (Article a : selected)
+ a.marked = !a.marked;
+
+ toggleArticlesMarked(selected);
+ hf.notifyUpdated();
+ } else {
+ Article article = hf.getArticleAtPosition(info.position);
+ if (article != null) {
+ article.marked = !article.marked;
+ saveArticleMarked(article);
+ hf.notifyUpdated();
+ }
+ }
+ }
+ return true;
+ case R.id.selection_toggle_published:
+ if (hf != null) {
+ ArticleList selected = hf.getSelectedArticles();
+
+ if (selected.size() > 0) {
+ for (Article a : selected)
+ a.published = !a.published;
+
+ toggleArticlesPublished(selected);
+ hf.notifyUpdated();
+ } else {
+ Article article = hf.getArticleAtPosition(info.position);
+ if (article != null) {
+ article.published = !article.published;
+ saveArticlePublished(article);
+ hf.notifyUpdated();
+ }
+ }
+ }
+ return true;
+ case R.id.selection_toggle_unread:
+ if (hf != null) {
+ ArticleList selected = hf.getSelectedArticles();
+
+ if (selected.size() > 0) {
+ for (Article a : selected)
+ a.unread = !a.unread;
+
+ toggleArticlesUnread(selected);
+ hf.notifyUpdated();
+ } else {
+ Article article = hf.getArticleAtPosition(info.position);
+ if (article != null) {
+ article.unread = !article.unread;
+ saveArticleUnread(article);
+ hf.notifyUpdated();
+ }
+ }
+ }
+ return true;
+ }
+
+ return true;
+ }
+
@Override
public Article getRelativeArticle(Article article, RelativeArticle ra) {