summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/layout-xlarge-port/headlines_row_selected.xml132
-rw-r--r--src/org/fox/ttrss/FeedCategoriesFragment.java5
-rw-r--r--src/org/fox/ttrss/FeedsFragment.java5
-rw-r--r--src/org/fox/ttrss/MainActivity.java13
-rw-r--r--src/org/fox/ttrss/offline/OfflineActivity.java207
-rw-r--r--src/org/fox/ttrss/offline/OfflineDownloadService.java6
-rw-r--r--src/org/fox/ttrss/offline/OfflineFeedCategoriesFragment.java271
-rw-r--r--src/org/fox/ttrss/offline/OfflineFeedsFragment.java24
-rw-r--r--src/org/fox/ttrss/offline/OfflineHeadlinesFragment.java20
-rw-r--r--src/org/fox/ttrss/offline/OfflineServices.java1
-rw-r--r--src/org/fox/ttrss/util/DatabaseHelper.java13
11 files changed, 636 insertions, 61 deletions
diff --git a/res/layout-xlarge-port/headlines_row_selected.xml b/res/layout-xlarge-port/headlines_row_selected.xml
new file mode 100644
index 00000000..3e476437
--- /dev/null
+++ b/res/layout-xlarge-port/headlines_row_selected.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/headlines_row"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="?headlineSelectedBackgroundSolid"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:id="@+id/linearLayout6"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="horizontal" >
+
+ <CheckBox
+ android:id="@+id/selected"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="false"
+ android:paddingLeft="6dip"
+ android:paddingRight="6dip" >
+ </CheckBox>
+
+ <LinearLayout
+ android:id="@+id/linearLayout1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:textColor="?headlineSelectedTextColor"
+ android:text="{Title...}"
+ android:textSize="16sp" >
+ </TextView>
+
+ <TextView
+ android:id="@+id/excerpt"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="{Content excerpt...}"
+ android:textColor="?headlineSelectedExcerptTextColor"
+ android:textSize="13sp" >
+ </TextView>
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/linerLayout3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:orientation="vertical"
+ android:padding="3dip" >
+
+ <TextView
+ android:id="@+id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Jan 01"
+ android:textColor="#909090"
+ android:textSize="13sp" >
+ </TextView>
+
+ <LinearLayout
+ android:id="@+id/linearLayout4"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:paddingRight="2sp" >
+
+ <ImageView
+ android:id="@+id/marked"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:src="@android:drawable/star_off" >
+ </ImageView>
+
+ <ImageView
+ android:id="@+id/published"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:src="@drawable/ic_rss_bw" >
+ </ImageView>
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:padding="3dip" >
+ </TextView>
+
+ <LinearLayout
+ android:id="@+id/attachments_holder"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0" >
+
+ <Spinner
+ android:id="@+id/attachments"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:prompt="@string/attachments_prompt" />
+
+ <Button
+ android:id="@+id/attachment_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:text="@string/attachment_view" />
+
+ <Button
+ android:id="@+id/attachment_copy"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:text="@string/attachment_copy" />
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file
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<String,String> map = new HashMap<String,String>() {
{
- 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