From 4f1c690e91f5f37aa24c336180120e451f87822a Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 22 Jun 2012 15:05:50 +0400 Subject: initial support for categories in offline mode layout tweaks --- src/org/fox/ttrss/FeedCategoriesFragment.java | 5 +- src/org/fox/ttrss/FeedsFragment.java | 5 +- src/org/fox/ttrss/MainActivity.java | 13 - src/org/fox/ttrss/offline/OfflineActivity.java | 207 +++++++++++++--- .../fox/ttrss/offline/OfflineDownloadService.java | 6 +- .../offline/OfflineFeedCategoriesFragment.java | 271 +++++++++++++++++++++ .../fox/ttrss/offline/OfflineFeedsFragment.java | 24 +- .../ttrss/offline/OfflineHeadlinesFragment.java | 20 +- src/org/fox/ttrss/offline/OfflineServices.java | 1 + src/org/fox/ttrss/util/DatabaseHelper.java | 13 + 10 files changed, 504 insertions(+), 61 deletions(-) create mode 100644 src/org/fox/ttrss/offline/OfflineFeedCategoriesFragment.java (limited to 'src') diff --git a/src/org/fox/ttrss/FeedCategoriesFragment.java b/src/org/fox/ttrss/FeedCategoriesFragment.java index b532df15..9b105b31 100644 --- a/src/org/fox/ttrss/FeedCategoriesFragment.java +++ b/src/org/fox/ttrss/FeedCategoriesFragment.java @@ -347,7 +347,10 @@ public class FeedCategoriesFragment extends Fragment implements OnItemClickListe if (list != null) { FeedCategory cat = (FeedCategory)list.getItemAtPosition(position); m_onlineServices.onCatSelected(cat); - m_selectedCat = cat; + + if (!m_onlineServices.isSmallScreen()) + m_selectedCat = cat; + m_adapter.notifyDataSetChanged(); } } diff --git a/src/org/fox/ttrss/FeedsFragment.java b/src/org/fox/ttrss/FeedsFragment.java index c10c9a45..0080c2d4 100644 --- a/src/org/fox/ttrss/FeedsFragment.java +++ b/src/org/fox/ttrss/FeedsFragment.java @@ -201,7 +201,10 @@ public class FeedsFragment extends Fragment implements OnItemClickListener, OnSh if (list != null) { Feed feed = (Feed)list.getItemAtPosition(position); m_onlineServices.onFeedSelected(feed); - m_selectedFeed = feed; + + if (!m_onlineServices.isSmallScreen()) + m_selectedFeed = feed; + m_adapter.notifyDataSetChanged(); } } diff --git a/src/org/fox/ttrss/MainActivity.java b/src/org/fox/ttrss/MainActivity.java index 206ea358..9760deb0 100644 --- a/src/org/fox/ttrss/MainActivity.java +++ b/src/org/fox/ttrss/MainActivity.java @@ -1694,19 +1694,6 @@ public class MainActivity extends FragmentActivity implements OnlineServices { sv.setQuery("", false); } } - - /* HeadlinesFragment frag = new HeadlinesFragment(m_activeFeed); - - FragmentTransaction ft = getSupportFragmentManager() - .beginTransaction(); - if (m_smallScreenMode) { - ft.replace(R.id.fragment_container, frag, FRAG_HEADLINES); - } else { - findViewById(R.id.headlines_fragment).setVisibility(View.VISIBLE); - ft.replace(R.id.headlines_fragment, frag, FRAG_HEADLINES); - } - ft.commit(); */ - viewFeed(feed, false); } diff --git a/src/org/fox/ttrss/offline/OfflineActivity.java b/src/org/fox/ttrss/offline/OfflineActivity.java index 6e85f8ba..6f507da5 100644 --- a/src/org/fox/ttrss/offline/OfflineActivity.java +++ b/src/org/fox/ttrss/offline/OfflineActivity.java @@ -5,8 +5,8 @@ import org.fox.ttrss.MainActivity; import org.fox.ttrss.OnlineServices; import org.fox.ttrss.OnlineServices.RelativeArticle; import org.fox.ttrss.PreferencesActivity; -import org.fox.ttrss.util.DatabaseHelper; import org.fox.ttrss.R; +import org.fox.ttrss.util.DatabaseHelper; import android.animation.LayoutTransition; import android.app.AlertDialog; @@ -35,12 +35,9 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.view.Window; -import android.view.animation.AnimationUtils; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.EditText; import android.widget.SearchView; -import android.widget.TextView; import android.widget.Toast; public class OfflineActivity extends FragmentActivity implements @@ -50,7 +47,7 @@ public class OfflineActivity extends FragmentActivity implements protected final static String FRAG_HEADLINES = "headlines"; protected final static String FRAG_ARTICLE = "article"; protected final static String FRAG_FEEDS = "feeds"; - //protected final static String FRAG_CATS = "cats"; + protected final static String FRAG_CATS = "cats"; private SharedPreferences m_prefs; private String m_themeName = ""; @@ -62,6 +59,8 @@ public class OfflineActivity extends FragmentActivity implements private boolean m_enableCats = false; private int m_activeFeedId = 0; + private boolean m_activeFeedIsCat = false; + private int m_activeCatId = -1; private int m_selectedArticleId = 0; private SQLiteDatabase m_readableDb; @@ -134,10 +133,12 @@ public class OfflineActivity extends FragmentActivity implements .getBoolean("unreadArticlesOnly"); m_activeFeedId = savedInstanceState.getInt("offlineActiveFeedId"); m_selectedArticleId = savedInstanceState.getInt("offlineArticleId"); + m_activeFeedIsCat = savedInstanceState.getBoolean("activeFeedIsCat"); + m_activeCatId = savedInstanceState.getInt("activeCatId"); } m_enableCats = m_prefs.getBoolean("enable_cats", false); - + m_smallScreenMode = m_compatMode || (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) != Configuration.SCREENLAYOUT_SIZE_XLARGE; @@ -148,7 +149,9 @@ public class OfflineActivity extends FragmentActivity implements if (!m_compatMode) { if (!m_smallScreenMode) { - findViewById(R.id.feeds_fragment).setVisibility(m_selectedArticleId != 0 ? View.GONE : View.VISIBLE); + int orientation = getWindowManager().getDefaultDisplay().getOrientation(); + + findViewById(R.id.feeds_fragment).setVisibility(m_selectedArticleId != 0 && orientation % 2 != 0 ? View.GONE : View.VISIBLE); findViewById(R.id.article_fragment).setVisibility(m_selectedArticleId != 0 ? View.VISIBLE : View.GONE); } @@ -162,14 +165,25 @@ public class OfflineActivity extends FragmentActivity implements findViewById(R.id.loading_container).setVisibility(View.GONE); - if (m_activeFeedId == 0) { + if (m_activeFeedId == 0 && !m_activeFeedIsCat) { FragmentTransaction ft = getSupportFragmentManager() .beginTransaction(); - OfflineFeedsFragment frag = new OfflineFeedsFragment(); + + Fragment frag = null; + String tag = null; + + if (m_enableCats) { + frag = new OfflineFeedCategoriesFragment(); + tag = FRAG_CATS; + } else { + frag = new OfflineFeedsFragment(); + tag = FRAG_FEEDS; + } + if (m_smallScreenMode) { - ft.replace(R.id.fragment_container, frag, FRAG_FEEDS); + ft.replace(R.id.fragment_container, frag, tag); } else { - ft.replace(R.id.feeds_fragment, frag, FRAG_FEEDS); + ft.replace(R.id.feeds_fragment, frag, tag); } ft.commit(); @@ -226,6 +240,8 @@ public class OfflineActivity extends FragmentActivity implements out.putBoolean("unreadArticlesOnly", m_unreadArticlesOnly); out.putInt("offlineActiveFeedId", m_activeFeedId); out.putInt("offlineArticleId", m_selectedArticleId); + out.putBoolean("activeFeedIsCat", m_activeFeedIsCat); + out.putInt("activeCatId", m_activeCatId); } private void setUnreadOnly(boolean unread) { @@ -290,41 +306,47 @@ public class OfflineActivity extends FragmentActivity implements private void goBack(boolean allowQuit) { if (m_smallScreenMode) { if (m_selectedArticleId != 0) { - closeArticle(); + closeArticle(); } else if (m_activeFeedId != 0) { m_activeFeedId = 0; - + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); - ft.replace(R.id.fragment_container, new OfflineFeedsFragment(), FRAG_FEEDS); + + if (m_activeFeedIsCat) { + ft.replace(R.id.fragment_container, new OfflineFeedCategoriesFragment(), FRAG_CATS); + } else { + ft.replace(R.id.fragment_container, new OfflineFeedsFragment(m_activeCatId), FRAG_FEEDS); + } ft.commit(); refreshViews(); initMainMenu(); - + } else if (m_activeCatId != -1) { + closeCategory(); } else if (allowQuit) { finish(); } } else { if (m_selectedArticleId != 0) { closeArticle(); - /* } else if (m_activeFeedId != 0) { - findViewById(R.id.headlines_fragment).setVisibility(View.INVISIBLE); + } else if (m_activeFeedId != 0) { m_activeFeedId = 0; OfflineFeedsFragment ff = (OfflineFeedsFragment) getSupportFragmentManager() .findFragmentByTag(FRAG_FEEDS); - if (ff != null) { - ff.setSelectedFeedId(0); - } - FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); - ft.replace(R.id.fragment_container, new OfflineHeadlinesFragment(), FRAG_HEADLINES); + ft.replace(R.id.headlines_fragment, new DummyFragment(), ""); ft.commit(); + + if (ff != null) { + ff.setSelectedFeedId(-1); + } refreshViews(); - initMainMenu(); */ - + initMainMenu(); + } else if (m_activeCatId != -1) { + closeCategory(); } else if (allowQuit) { finish(); } @@ -383,6 +405,16 @@ public class OfflineActivity extends FragmentActivity implements return c; } + private Cursor getCatById(int catId) { + Cursor c = getReadableDb().query("categories", null, + BaseColumns._ID + "=?", + new String[] { String.valueOf(catId) }, null, null, null); + + c.moveToFirst(); + + return c; + } + private Intent getShareIntent(Cursor article) { String title = article.getString(article.getColumnIndex("title")); String link = article.getString(article.getColumnIndex("link")); @@ -647,10 +679,16 @@ public class OfflineActivity extends FragmentActivity implements } } - private void closeArticle() { - // we don't want to lose selected article in headlines so we refresh them before setting selected id to 0 - refreshViews(); + private void refreshCats() { + OfflineFeedCategoriesFragment frag = (OfflineFeedCategoriesFragment) getSupportFragmentManager() + .findFragmentByTag(FRAG_CATS); + if (frag != null) { + frag.refresh(); + } + } + + private void closeArticle() { m_selectedArticleId = 0; FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); @@ -666,6 +704,8 @@ public class OfflineActivity extends FragmentActivity implements ft.commit(); initMainMenu(); + + refreshViews(); } private int getSelectedArticleCount() { @@ -749,11 +789,26 @@ public class OfflineActivity extends FragmentActivity implements if (!m_compatMode) { if (m_activeFeedId != 0) { - Cursor feed = getFeedById(m_activeFeedId); + if (!m_activeFeedIsCat) { + Cursor feed = getFeedById(m_activeFeedId); - if (feed != null) { - getActionBar().setTitle(feed.getString(feed.getColumnIndex("title"))); + if (feed != null) { + getActionBar().setTitle(feed.getString(feed.getColumnIndex("title"))); + } + } else { + Cursor cat = getCatById(m_activeFeedId); + + if (cat != null) { + getActionBar().setTitle(cat.getString(cat.getColumnIndex("title"))); + } } + } else if (m_activeCatId != -1) { + Cursor cat = getCatById(m_activeCatId); + + if (cat != null) { + getActionBar().setTitle(cat.getString(cat.getColumnIndex("title"))); + } + } else { getActionBar().setTitle(R.string.app_name); } @@ -784,6 +839,7 @@ public class OfflineActivity extends FragmentActivity implements private void refreshViews() { refreshFeeds(); + refreshCats(); refreshHeadlines(); } @@ -796,6 +852,8 @@ public class OfflineActivity extends FragmentActivity implements .findFragmentByTag(FRAG_HEADLINES); OfflineFeedsFragment ff = (OfflineFeedsFragment) getSupportFragmentManager() .findFragmentByTag(FRAG_FEEDS); + OfflineFeedCategoriesFragment cf = (OfflineFeedCategoriesFragment) getSupportFragmentManager() + .findFragmentByTag(FRAG_CATS); switch (item.getItemId()) { case R.id.article_link_copy: @@ -832,13 +890,29 @@ public class OfflineActivity extends FragmentActivity implements return true; case R.id.browse_articles: - // TODO cat stuff + if (cf != null) { + int catId = cf.getCatIdAtPosition(info.position); + viewFeed(catId, true); + } return true; case R.id.browse_feeds: - // TODO cat stuff + if (cf != null) { + int catId = cf.getCatIdAtPosition(info.position); + viewCategory(catId, false); + } return true; case R.id.catchup_category: - // TODO cat stuff + if (cf != null) { + int catId = cf.getCatIdAtPosition(info.position); + + SQLiteStatement stmt = getWritableDb().compileStatement( + "UPDATE articles SET unread = 0 WHERE feed_id IN (SELECT "+ + BaseColumns._ID+" FROM feeds WHERE cat_id = ?)"); + stmt.bindLong(1, catId); + stmt.execute(); + stmt.close(); + refreshViews(); + } return true; case R.id.catchup_feed: if (ff != null) { @@ -1071,9 +1145,55 @@ public class OfflineActivity extends FragmentActivity implements return id; } + public void onCatSelected(int catId) { + Log.d(TAG, "onCatSelected"); + boolean browse = m_prefs.getBoolean("browse_cats_like_feeds", false); + + viewCategory(catId, browse); + } + + public void viewCategory(int cat, boolean openAsFeed) { + + Log.d(TAG, "viewCategory"); + + if (!openAsFeed) { + OfflineFeedsFragment frag = new OfflineFeedsFragment(cat); + + FragmentTransaction ft = getSupportFragmentManager() + .beginTransaction(); + + if (m_smallScreenMode) { + ft.replace(R.id.fragment_container, frag, FRAG_FEEDS); + } else { + ft.replace(R.id.feeds_fragment, frag, FRAG_FEEDS); + } + ft.commit(); + + m_activeCatId = cat; + + } else { + if (m_menu != null) { + MenuItem search = m_menu.findItem(R.id.search); + + if (search != null && !m_compatMode) { + SearchView sv = (SearchView) search.getActionView(); + sv.setQuery("", false); + } + } + viewFeed(cat, true); + } + + initMainMenu(); + } + @Override public void viewFeed(int feedId) { + viewFeed(feedId, false); + } + + public void viewFeed(int feedId, boolean isCat) { m_activeFeedId = feedId; + m_activeFeedIsCat = isCat; initMainMenu(); @@ -1089,7 +1209,7 @@ public class OfflineActivity extends FragmentActivity implements } FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); - OfflineHeadlinesFragment frag = new OfflineHeadlinesFragment(feedId); + OfflineHeadlinesFragment frag = new OfflineHeadlinesFragment(feedId, isCat); if (m_smallScreenMode) { ft.replace(R.id.fragment_container, frag, FRAG_HEADLINES); @@ -1136,9 +1256,10 @@ public class OfflineActivity extends FragmentActivity implements ft.hide(getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES)); ft.add(R.id.fragment_container, frag, FRAG_ARTICLE); } else { - findViewById(R.id.feeds_fragment).setVisibility(View.GONE); findViewById(R.id.article_fragment).setVisibility(View.VISIBLE); ft.replace(R.id.article_fragment, frag, FRAG_ARTICLE); + + refreshViews(); } ft.commit(); @@ -1154,4 +1275,20 @@ public class OfflineActivity extends FragmentActivity implements m_selectedArticleId = articleId; refreshViews(); } + + private void closeCategory() { + m_activeCatId = -1; + + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + if (m_smallScreenMode) { + ft.replace(R.id.fragment_container, new OfflineFeedCategoriesFragment(), FRAG_CATS); + } else { + ft.replace(R.id.feeds_fragment, new OfflineFeedCategoriesFragment(), FRAG_CATS); + } + ft.commit(); + + initMainMenu(); + + refreshViews(); + } } \ No newline at end of file diff --git a/src/org/fox/ttrss/offline/OfflineDownloadService.java b/src/org/fox/ttrss/offline/OfflineDownloadService.java index 98c8ce8a..15477033 100644 --- a/src/org/fox/ttrss/offline/OfflineDownloadService.java +++ b/src/org/fox/ttrss/offline/OfflineDownloadService.java @@ -316,9 +316,9 @@ public class OfflineDownloadService extends Service { @SuppressWarnings("serial") HashMap map = new HashMap() { { - put("op", "getFeeds"); + put("op", "getCategories"); put("sid", m_sessionId); - put("cat_id", "-3"); + //put("cat_id", "-3"); put("unread_only", "true"); } }; @@ -451,7 +451,7 @@ public class OfflineDownloadService extends Service { updateNotification(R.string.notify_downloading_init); m_downloadInProgress = true; - downloadFeeds(); + downloadCategories(); } } } diff --git a/src/org/fox/ttrss/offline/OfflineFeedCategoriesFragment.java b/src/org/fox/ttrss/offline/OfflineFeedCategoriesFragment.java new file mode 100644 index 00000000..13b28f53 --- /dev/null +++ b/src/org/fox/ttrss/offline/OfflineFeedCategoriesFragment.java @@ -0,0 +1,271 @@ +package org.fox.ttrss.offline; + +import java.io.File; + +import org.fox.ttrss.R; +import org.fox.ttrss.R.drawable; +import org.fox.ttrss.R.id; +import org.fox.ttrss.R.layout; +import org.fox.ttrss.R.menu; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.os.Environment; +import android.preference.PreferenceManager; +import android.provider.BaseColumns; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SimpleCursorAdapter; +import android.util.Log; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.AdapterContextMenuInfo; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +public class OfflineFeedCategoriesFragment extends Fragment implements OnItemClickListener, OnSharedPreferenceChangeListener { + private final String TAG = this.getClass().getSimpleName(); + private SharedPreferences m_prefs; + private FeedCategoryListAdapter m_adapter; + private int m_selectedCatId; + private Cursor m_cursor; + private OfflineServices m_offlineServices; + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + + getActivity().getMenuInflater().inflate(R.menu.category_menu, menu); + + AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; + Cursor cursor = (Cursor)m_adapter.getItem(info.position); + + if (cursor != null) + menu.setHeaderTitle(cursor.getString(cursor.getColumnIndex("title"))); + + super.onCreateContextMenu(menu, v, menuInfo); + + } + + public Cursor createCursor() { + String unreadOnly = BaseColumns._ID + "> 0 AND " + (m_offlineServices.getUnreadOnly() ? "unread > 0" : "1"); + + String order = m_prefs.getBoolean("sort_feeds_by_unread", false) ? "unread DESC, title" : "title"; + + return m_offlineServices.getReadableDb().query("cats_unread", + null, unreadOnly, null, null, null, order); + } + + public void refresh() { + if (m_cursor != null && !m_cursor.isClosed()) m_cursor.close(); + + m_cursor = createCursor(); + + if (m_cursor != null) { + m_adapter.changeCursor(m_cursor); + m_adapter.notifyDataSetChanged(); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + + if (savedInstanceState != null) { + m_selectedCatId = savedInstanceState.getInt("selectedFeedId"); + } + + View view = inflater.inflate(R.layout.feeds_fragment, container, false); + + ListView list = (ListView)view.findViewById(R.id.feeds); + + m_cursor = createCursor(); + + m_adapter = new FeedCategoryListAdapter(getActivity(), R.layout.feeds_row, m_cursor, + new String[] { "title", "unread" }, new int[] { R.id.title, R.id.unread_counter }, 0); + + list.setAdapter(m_adapter); + list.setOnItemClickListener(this); + list.setEmptyView(view.findViewById(R.id.no_feeds)); + registerForContextMenu(list); + + view.findViewById(R.id.loading_container).setVisibility(View.GONE); + + return view; + } + + @Override + public void onDestroy() { + super.onDestroy(); + + if (m_cursor != null && !m_cursor.isClosed()) m_cursor.close(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + m_offlineServices = (OfflineServices)activity; + + m_prefs = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext()); + m_prefs.registerOnSharedPreferenceChangeListener(this); + + } + + @Override + public void onSaveInstanceState (Bundle out) { + super.onSaveInstanceState(out); + + out.putInt("selectedFeedId", m_selectedCatId); + } + + @Override + public void onItemClick(AdapterView av, View view, int position, long id) { + ListView list = (ListView)getActivity().findViewById(R.id.feeds); + + if (list != null) { + Cursor cursor = (Cursor) list.getItemAtPosition(position); + + if (cursor != null) { + int feedId = (int) cursor.getLong(0); + Log.d(TAG, "clicked on feed " + feedId); + + m_offlineServices.onCatSelected(feedId); + + if (!m_offlineServices.isSmallScreen()) + m_selectedCatId = feedId; + + m_adapter.notifyDataSetChanged(); + } + } + } + + /* public void setLoadingStatus(int status, boolean showProgress) { + if (getView() != null) { + TextView tv = (TextView)getView().findViewById(R.id.loading_message); + + if (tv != null) { + tv.setText(status); + } + } + + getActivity().setProgressBarIndeterminateVisibility(showProgress); + } */ + + private class FeedCategoryListAdapter extends SimpleCursorAdapter { + + + public FeedCategoryListAdapter(Context context, int layout, Cursor c, + String[] from, int[] to, int flags) { + super(context, layout, c, from, to, flags); + } + + public static final int VIEW_NORMAL = 0; + public static final int VIEW_SELECTED = 1; + + public static final int VIEW_COUNT = VIEW_SELECTED+1; + + @Override + public int getViewTypeCount() { + return VIEW_COUNT; + } + + @Override + public int getItemViewType(int position) { + Cursor cursor = (Cursor) this.getItem(position); + + if (cursor.getLong(0) == m_selectedCatId) { + return VIEW_SELECTED; + } else { + return VIEW_NORMAL; + } + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View v = convertView; + + Cursor cursor = (Cursor)getItem(position); + + if (v == null) { + int layoutId = R.layout.feeds_row; + + switch (getItemViewType(position)) { + case VIEW_SELECTED: + layoutId = R.layout.feeds_row_selected; + break; + } + + LayoutInflater vi = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = vi.inflate(layoutId, null); + + } + + TextView tt = (TextView) v.findViewById(R.id.title); + + if (tt != null) { + tt.setText(cursor.getString(cursor.getColumnIndex("title"))); + } + + TextView tu = (TextView) v.findViewById(R.id.unread_counter); + + if (tu != null) { + tu.setText(String.valueOf(cursor.getInt(cursor.getColumnIndex("unread")))); + tu.setVisibility((cursor.getInt(cursor.getColumnIndex("unread")) > 0) ? View.VISIBLE : View.INVISIBLE); + } + + ImageView icon = (ImageView)v.findViewById(R.id.icon); + + if (icon != null) { + icon.setImageResource(cursor.getInt(cursor.getColumnIndex("unread")) > 0 ? R.drawable.ic_rss : R.drawable.ic_rss_bw); + } + + return v; + } + } + + public void sortCategories() { + try { + refresh(); + } catch (NullPointerException e) { + // activity is gone? + } catch (IllegalStateException e) { + // we're probably closing and DB is gone already + } + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + + sortCategories(); + } + + public int getCatIdAtPosition(int position) { + Cursor c = (Cursor)m_adapter.getItem(position); + + if (c != null) { + int catId = c.getInt(0); + c.close(); + return catId; + } + + return 0; + } + + public void setSelectedFeedId(int feedId) { + m_selectedCatId = feedId; + refresh(); + } + +} diff --git a/src/org/fox/ttrss/offline/OfflineFeedsFragment.java b/src/org/fox/ttrss/offline/OfflineFeedsFragment.java index 682fb168..ee91eb5b 100644 --- a/src/org/fox/ttrss/offline/OfflineFeedsFragment.java +++ b/src/org/fox/ttrss/offline/OfflineFeedsFragment.java @@ -40,10 +40,19 @@ public class OfflineFeedsFragment extends Fragment implements OnItemClickListene private FeedListAdapter m_adapter; private static final String ICON_PATH = "/data/org.fox.ttrss/icons/"; private int m_selectedFeedId; + private int m_catId = -1; private boolean m_enableFeedIcons; private Cursor m_cursor; private OfflineServices m_offlineServices; + public OfflineFeedsFragment() { + // + } + + public OfflineFeedsFragment(int catId) { + m_catId = catId; + } + @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { @@ -61,12 +70,16 @@ public class OfflineFeedsFragment extends Fragment implements OnItemClickListene } public Cursor createCursor() { - String unreadOnly = m_offlineServices.getUnreadOnly() ? "unread > 0" : null; - + String unreadOnly = m_offlineServices.getUnreadOnly() ? "unread > 0" : "1"; String order = m_prefs.getBoolean("sort_feeds_by_unread", false) ? "unread DESC, title" : "title"; - return m_offlineServices.getReadableDb().query("feeds_unread", + if (m_catId != -1) { + return m_offlineServices.getReadableDb().query("feeds_unread", + null, unreadOnly + " AND cat_id = ?", new String[] { String.valueOf(m_catId) }, null, null, order); + } else { + return m_offlineServices.getReadableDb().query("feeds_unread", null, unreadOnly, null, null, null, order); + } } public void refresh() { @@ -85,6 +98,7 @@ public class OfflineFeedsFragment extends Fragment implements OnItemClickListene if (savedInstanceState != null) { m_selectedFeedId = savedInstanceState.getInt("selectedFeedId"); + m_catId = savedInstanceState.getInt("catId"); } View view = inflater.inflate(R.layout.feeds_fragment, container, false); @@ -131,6 +145,7 @@ public class OfflineFeedsFragment extends Fragment implements OnItemClickListene super.onSaveInstanceState(out); out.putInt("selectedFeedId", m_selectedFeedId); + out.putInt("catId", m_catId); } @Override @@ -146,7 +161,8 @@ public class OfflineFeedsFragment extends Fragment implements OnItemClickListene m_offlineServices.viewFeed(feedId); - m_selectedFeedId = feedId; + if (!m_offlineServices.isSmallScreen()) + m_selectedFeedId = feedId; m_adapter.notifyDataSetChanged(); } diff --git a/src/org/fox/ttrss/offline/OfflineHeadlinesFragment.java b/src/org/fox/ttrss/offline/OfflineHeadlinesFragment.java index b3727535..d25c7b65 100644 --- a/src/org/fox/ttrss/offline/OfflineHeadlinesFragment.java +++ b/src/org/fox/ttrss/offline/OfflineHeadlinesFragment.java @@ -49,6 +49,7 @@ public class OfflineHeadlinesFragment extends Fragment implements OnItemClickLis private final String TAG = this.getClass().getSimpleName(); private int m_feedId; + private boolean m_feedIsCat = false; private int m_activeArticleId; private boolean m_combinedMode = true; private String m_searchQuery = ""; @@ -69,10 +70,11 @@ public class OfflineHeadlinesFragment extends Fragment implements OnItemClickLis }; - public OfflineHeadlinesFragment(int feedId) { + public OfflineHeadlinesFragment(int feedId, boolean isCat) { m_feedId = feedId; + m_feedIsCat = isCat; } - + public OfflineHeadlinesFragment() { // } @@ -136,6 +138,7 @@ public class OfflineHeadlinesFragment extends Fragment implements OnItemClickLis //m_selectedArticles = savedInstanceState.getParcelableArrayList("selectedArticles"); m_combinedMode = savedInstanceState.getBoolean("combinedMode"); m_searchQuery = (String) savedInstanceState.getCharSequence("searchQuery"); + m_feedIsCat = savedInstanceState.getBoolean("feedIsCat"); } View view = inflater.inflate(R.layout.headlines_fragment, container, false); @@ -160,12 +163,20 @@ public class OfflineHeadlinesFragment extends Fragment implements OnItemClickLis } public Cursor createCursor() { + String feedClause = null; + + if (m_feedIsCat) { + feedClause = "feed_id IN (SELECT "+BaseColumns._ID+" FROM feeds WHERE cat_id = ?)"; + } else { + feedClause = "feed_id = ?"; + } + if (m_searchQuery.equals("")) { return m_offlineServices.getReadableDb().query("articles", - null, "feed_id = ?", new String[] { String.valueOf(m_feedId) }, null, null, "updated DESC"); + null, feedClause, new String[] { String.valueOf(m_feedId) }, null, null, "updated DESC"); } else { return m_offlineServices.getReadableDb().query("articles", - null, "feed_id = ? AND (title LIKE '%' || ? || '%' OR content LIKE '%' || ? || '%')", + null, feedClause + " AND (title LIKE '%' || ? || '%' OR content LIKE '%' || ? || '%')", new String[] { String.valueOf(m_feedId), m_searchQuery, m_searchQuery }, null, null, "updated DESC"); } } @@ -214,6 +225,7 @@ public class OfflineHeadlinesFragment extends Fragment implements OnItemClickLis //out.putParcelableArrayList("selectedArticles", m_selectedArticles); out.putBoolean("combinedMode", m_combinedMode); out.putCharSequence("searchQuery", m_searchQuery); + out.putBoolean("feedIsCat", m_feedIsCat); } /* public void setLoadingStatus(int status, boolean showProgress) { diff --git a/src/org/fox/ttrss/offline/OfflineServices.java b/src/org/fox/ttrss/offline/OfflineServices.java index 0ad6bd8c..b75d75a4 100644 --- a/src/org/fox/ttrss/offline/OfflineServices.java +++ b/src/org/fox/ttrss/offline/OfflineServices.java @@ -11,6 +11,7 @@ public interface OfflineServices { public SQLiteDatabase getWritableDb(); public int getRelativeArticleId(int baseId, int feedId, OnlineServices.RelativeArticle mode); public void viewFeed(int feedId); + public void onCatSelected(int catId); public void openArticle(int articleId, int compatAnimation); public boolean getUnreadOnly(); public int getSelectedArticleId(); diff --git a/src/org/fox/ttrss/util/DatabaseHelper.java b/src/org/fox/ttrss/util/DatabaseHelper.java index 345e0782..501aadd1 100644 --- a/src/org/fox/ttrss/util/DatabaseHelper.java +++ b/src/org/fox/ttrss/util/DatabaseHelper.java @@ -60,9 +60,22 @@ public class DatabaseHelper extends SQLiteOpenHelper { db.execSQL("CREATE VIEW feeds_unread AS SELECT feeds."+BaseColumns._ID+" AS "+BaseColumns._ID+", " + "feeds.title AS title, " + + "cat_id, " + "SUM(articles.unread) AS unread FROM feeds " + "LEFT JOIN articles ON (articles.feed_id = feeds."+BaseColumns._ID+") " + "GROUP BY feeds."+BaseColumns._ID+", feeds.title;"); + + //sqlite> select categories._id,categories.title,sum(articles.unread) from categories left j + //oin feeds on (feeds.cat_id = categories._id) left join articles on (articles.feed_id = fee + //ds._id) group by categories._id; + + db.execSQL("CREATE VIEW cats_unread AS SELECT categories."+BaseColumns._ID+" AS "+BaseColumns._ID+", " + + "categories.title AS title, " + + "SUM(articles.unread) AS unread FROM categories " + + "LEFT JOIN feeds ON (feeds.cat_id = categories."+BaseColumns._ID+") "+ + "LEFT JOIN articles ON (articles.feed_id = feeds."+BaseColumns._ID+") " + + "GROUP BY categories."+BaseColumns._ID+", categories.title;"); + } @Override -- cgit v1.2.3-54-g00ecf