From 6a9178fe2e3f3160d05bbe4f197cf040ca1409cc Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 5 Dec 2011 20:22:31 +0300 Subject: implement offline feedlist --- src/org/fox/ttrss/MainActivity.java | 139 +++++++++++----- src/org/fox/ttrss/OfflineFeedsFragment.java | 250 ++++++++++++++++++++++++++++ 2 files changed, 348 insertions(+), 41 deletions(-) create mode 100644 src/org/fox/ttrss/OfflineFeedsFragment.java (limited to 'src') diff --git a/src/org/fox/ttrss/MainActivity.java b/src/org/fox/ttrss/MainActivity.java index 0034d842..32040b69 100644 --- a/src/org/fox/ttrss/MainActivity.java +++ b/src/org/fox/ttrss/MainActivity.java @@ -61,6 +61,8 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe private int m_articleOffset = 0; private boolean m_isOffline = false; + private int m_activeOfflineFeedId = 0; + private SQLiteDatabase m_readableDb; private SQLiteDatabase m_writableDb; @@ -320,6 +322,7 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe m_apiLevel = savedInstanceState.getInt("apiLevel"); m_isLicensed = savedInstanceState.getInt("isLicensed"); m_isOffline = savedInstanceState.getBoolean("isOffline"); + m_activeOfflineFeedId = savedInstanceState.getInt("offlineActiveFeedId"); } m_enableCats = m_prefs.getBoolean("enable_cats", false); @@ -334,6 +337,10 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe m_smallScreenMode = width < 960 || height < 720; setContentView(R.layout.main); + + initDatabase(); + + m_isOffline = true; Log.d(TAG, "m_isOffline=" + m_isOffline); Log.d(TAG, "m_smallScreenMode=" + m_smallScreenMode); @@ -353,51 +360,57 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe } } - if (m_smallScreenMode) { - if (m_selectedArticle != null) { - findViewById(R.id.feeds_fragment).setVisibility(View.GONE); - findViewById(R.id.cats_fragment).setVisibility(View.GONE); - findViewById(R.id.headlines_fragment).setVisibility(View.GONE); - } else if (m_activeFeed != null) { - findViewById(R.id.feeds_fragment).setVisibility(View.GONE); - findViewById(R.id.article_fragment).setVisibility(View.GONE); - findViewById(R.id.cats_fragment).setVisibility(View.GONE); + if (m_isOffline) { + findViewById(R.id.cats_fragment).setVisibility(View.GONE); + findViewById(R.id.headlines_fragment).setVisibility(View.GONE); + findViewById(R.id.article_fragment).setVisibility(View.GONE); + } else { + + if (m_smallScreenMode) { + if (m_selectedArticle != null) { + findViewById(R.id.feeds_fragment).setVisibility(View.GONE); + findViewById(R.id.cats_fragment).setVisibility(View.GONE); + findViewById(R.id.headlines_fragment).setVisibility(View.GONE); + } else if (m_activeFeed != null) { + findViewById(R.id.feeds_fragment).setVisibility(View.GONE); + findViewById(R.id.article_fragment).setVisibility(View.GONE); + findViewById(R.id.cats_fragment).setVisibility(View.GONE); + } else { + findViewById(R.id.headlines_fragment).setVisibility(View.GONE); + //findViewById(R.id.article_fragment).setVisibility(View.GONE); + + if (m_enableCats && m_activeCategory == null) { + findViewById(R.id.feeds_fragment).setVisibility(View.GONE); + findViewById(R.id.cats_fragment).setVisibility(View.VISIBLE); + } else { + findViewById(R.id.cats_fragment).setVisibility(View.GONE); + } + } } else { - findViewById(R.id.headlines_fragment).setVisibility(View.GONE); - //findViewById(R.id.article_fragment).setVisibility(View.GONE); + if (m_selectedArticle == null) { + findViewById(R.id.article_fragment).setVisibility(View.GONE); + + if (!m_enableCats || m_activeCategory != null) + findViewById(R.id.cats_fragment).setVisibility(View.GONE); + else + findViewById(R.id.feeds_fragment).setVisibility(View.GONE); - if (m_enableCats && m_activeCategory == null) { - findViewById(R.id.feeds_fragment).setVisibility(View.GONE); - findViewById(R.id.cats_fragment).setVisibility(View.VISIBLE); } else { + findViewById(R.id.feeds_fragment).setVisibility(View.GONE); findViewById(R.id.cats_fragment).setVisibility(View.GONE); } } + } + + if (m_isOffline) { + switchOffline(); } else { - if (m_selectedArticle == null) { - findViewById(R.id.article_fragment).setVisibility(View.GONE); - - if (!m_enableCats || m_activeCategory != null) - findViewById(R.id.cats_fragment).setVisibility(View.GONE); - else - findViewById(R.id.feeds_fragment).setVisibility(View.GONE); - + if (m_sessionId != null) { + loginSuccess(); } else { - findViewById(R.id.feeds_fragment).setVisibility(View.GONE); - findViewById(R.id.cats_fragment).setVisibility(View.GONE); + login(); } - - } - - initDatabase(); - - if (m_sessionId != null) { - loginSuccess(); - } else { - login(); - } - } @@ -407,6 +420,10 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe m_readableDb = dh.getReadableDatabase(); } + public synchronized SQLiteDatabase getReadableDb() { + return m_readableDb; + } + public synchronized SQLiteDatabase getWritableDb() { return m_writableDb; } @@ -501,7 +518,30 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe }; req.execute(map); - } + } else { + switchOfflineSuccess(); + } + } + + public void switchOfflineSuccess() { + logout(); + //setLoadingStatus(R.string.blank, false); + + m_isOffline = true; + initMainMenu(); + + findViewById(R.id.loading_container).setVisibility(View.INVISIBLE); + findViewById(R.id.main).setVisibility(View.VISIBLE); + + if (m_activeOfflineFeedId == 0) { + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + OfflineFeedsFragment frag = new OfflineFeedsFragment(); + ft.replace(R.id.feeds_fragment, frag); + ft.commit(); + } else { + offlineViewFeed(m_activeOfflineFeedId); + } + } public void setLoadingStatus(int status, boolean showProgress) { @@ -531,6 +571,7 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe out.putInt("apiLevel", m_apiLevel); out.putInt("isLicensed", m_isLicensed); out.putBoolean("isOffline", m_isOffline); + out.putInt("offlineActiveFeedId", m_activeOfflineFeedId); } @Override @@ -969,7 +1010,13 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe m_menu.setGroupVisible(R.id.menu_group_headlines, false); m_menu.setGroupVisible(R.id.menu_group_article, false); m_menu.setGroupVisible(R.id.menu_group_headlines_selection, false); - m_menu.setGroupVisible(R.id.menu_group_logged_out, true); + + if (m_isOffline) { + m_menu.setGroupVisible(R.id.menu_group_logged_out, false); + + } else { + m_menu.setGroupVisible(R.id.menu_group_logged_out, true); + } } } } @@ -990,6 +1037,15 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe } + @Override + public void onDestroy() { + super.onDestroy(); + + m_readableDb.close(); + m_writableDb.close(); + + } + private void loginSuccess() { findViewById(R.id.loading_container).setVisibility(View.INVISIBLE); findViewById(R.id.main).setVisibility(View.VISIBLE); @@ -1546,10 +1602,7 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe if (articles.size() == 30 && m_articleOffset < 500) { offlineGetArticles(); } else { - logout(); - setLoadingStatus(R.string.blank, false); - m_isOffline = true; - initMainMenu(); + switchOfflineSuccess(); } return; @@ -1566,4 +1619,8 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe } } } + + public void offlineViewFeed(int feedId) { + m_activeOfflineFeedId = feedId; + } } \ No newline at end of file diff --git a/src/org/fox/ttrss/OfflineFeedsFragment.java b/src/org/fox/ttrss/OfflineFeedsFragment.java new file mode 100644 index 00000000..992adab1 --- /dev/null +++ b/src/org/fox/ttrss/OfflineFeedsFragment.java @@ -0,0 +1,250 @@ +package org.fox.ttrss; + +import java.io.File; + +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.BaseAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +public class OfflineFeedsFragment extends Fragment implements OnItemClickListener, OnSharedPreferenceChangeListener { + private final String TAG = this.getClass().getSimpleName(); + private SharedPreferences m_prefs; + private FeedListAdapter m_adapter; + private static final String ICON_PATH = "/org.fox.ttrss/icons/"; + private int m_selectedFeedId; + private boolean m_enableFeedIcons; + private Cursor m_cursor; + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + + getActivity().getMenuInflater().inflate(R.menu.feed_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); + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + + if (savedInstanceState != null) { + m_selectedFeedId = savedInstanceState.getInt("selectedFeedId"); + } + + View view = inflater.inflate(R.layout.feeds_fragment, container, false); + + ListView list = (ListView)view.findViewById(R.id.feeds); + + m_cursor = ((MainActivity)getActivity()).getReadableDb().query("feeds_unread", + null, null, null, null, null, "title"); + + m_adapter = new FeedListAdapter(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_unread_feeds)); + registerForContextMenu(list); + + view.findViewById(R.id.loading_container).setVisibility(View.GONE); + + m_enableFeedIcons = m_prefs.getBoolean("download_feed_icons", false); + + return view; + } + + @Override + public void onDestroy() { + super.onDestroy(); + + m_cursor.close(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + m_prefs = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext()); + m_prefs.registerOnSharedPreferenceChangeListener(this); + + } + + @Override + public void onSaveInstanceState (Bundle out) { + super.onSaveInstanceState(out); + + out.putInt("selectedFeedId", m_selectedFeedId); + } + + @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); + + ((MainActivity)getActivity()).offlineViewFeed(feedId); + + m_selectedFeedId = 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); + } + + View pb = getView().findViewById(R.id.loading_progress); + + if (pb != null) { + pb.setVisibility(showProgress ? View.VISIBLE : View.GONE); + } + } + } + + private class FeedListAdapter extends SimpleCursorAdapter { + + + public FeedListAdapter(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_selectedFeedId) { + 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) { + + if (m_enableFeedIcons) { + + File storage = Environment.getExternalStorageDirectory(); + + File iconFile = new File(storage.getAbsolutePath() + ICON_PATH + cursor.getInt(cursor.getColumnIndex(BaseColumns._ID)) + ".ico"); + if (iconFile.exists()) { + Bitmap bmpOrig = BitmapFactory.decodeFile(iconFile.getAbsolutePath()); + if (bmpOrig != null) { + icon.setImageBitmap(bmpOrig); + } + } else { + icon.setImageResource(cursor.getInt(cursor.getColumnIndex("unread")) > 0 ? R.drawable.ic_rss : R.drawable.ic_rss_bw); + } + + } else { + icon.setImageResource(cursor.getInt(cursor.getColumnIndex("unread")) > 0 ? R.drawable.ic_rss : R.drawable.ic_rss_bw); + } + + } + + return v; + } + } + + public void sortFeeds() { + // TODO implement + + m_adapter.notifyDataSetInvalidated(); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + + sortFeeds(); + m_enableFeedIcons = m_prefs.getBoolean("download_feed_icons", false); + + } + +} -- cgit v1.2.3-54-g00ecf