From ced80be1aea975b59db5a0e6dd14acb054e7910e Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 16 Sep 2012 13:25:28 +0400 Subject: initial --- .../fox/ttrss/offline/OfflineFeedsFragment.java | 306 --------------------- 1 file changed, 306 deletions(-) delete mode 100644 src/org/fox/ttrss/offline/OfflineFeedsFragment.java (limited to 'src/org/fox/ttrss/offline/OfflineFeedsFragment.java') diff --git a/src/org/fox/ttrss/offline/OfflineFeedsFragment.java b/src/org/fox/ttrss/offline/OfflineFeedsFragment.java deleted file mode 100644 index 605f506c..00000000 --- a/src/org/fox/ttrss/offline/OfflineFeedsFragment.java +++ /dev/null @@ -1,306 +0,0 @@ -package org.fox.ttrss.offline; - -import java.io.File; - -import org.fox.ttrss.R; - -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 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 = "/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) { - - 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); - - } - - public Cursor createCursor() { - String unreadOnly = m_offlineServices.getUnreadOnly() ? "unread > 0" : "1"; - String order = m_prefs.getBoolean("sort_feeds_by_unread", false) ? "unread DESC, title" : "title"; - - 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() { - 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_selectedFeedId = savedInstanceState.getInt("selectedFeedId"); - m_catId = savedInstanceState.getInt("catId"); - } - - View view = inflater.inflate(R.layout.feeds_fragment, container, false); - - ListView list = (ListView)view.findViewById(R.id.feeds); - - m_cursor = createCursor(); - - 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_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(); - - 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_selectedFeedId); - out.putInt("catId", m_catId); - } - - @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.onFeedSelected(feedId); - - if (!m_offlineServices.isSmallScreen()) - 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); - } - } - - getActivity().setProgressBarIndeterminateVisibility(showProgress); - } */ - - 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 (!m_offlineServices.isSmallScreen() && 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() { - 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) { - - sortFeeds(); - m_enableFeedIcons = m_prefs.getBoolean("download_feed_icons", false); - - } - - public int getFeedIdAtPosition(int position) { - Cursor c = (Cursor)m_adapter.getItem(position); - - if (c != null) { - int feedId = c.getInt(0); - c.close(); - return feedId; - } - - return 0; - } - - public void setSelectedFeedId(int feedId) { - m_selectedFeedId = feedId; - refresh(); - } - -} -- cgit v1.2.3-54-g00ecf From 4eac5b73bb4e3d91794a688d7e760e1f6e629c88 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 17 Sep 2012 16:28:32 +0400 Subject: implement core offline functions --- AndroidManifest.xml | 15 + src/org/fox/ttrss/ArticleEventListener.java | 9 - src/org/fox/ttrss/ArticleFragment.java | 8 +- src/org/fox/ttrss/FeedsActivity.java | 2 +- src/org/fox/ttrss/FeedsEventListener.java | 5 - src/org/fox/ttrss/HeadlinesActivity.java | 2 +- src/org/fox/ttrss/OnlineActivity.java | 309 ++++++++++- src/org/fox/ttrss/offline/OfflineActivity.java | 192 +++++++ .../ttrss/offline/OfflineArticleEventListener.java | 5 + .../fox/ttrss/offline/OfflineArticleFragment.java | 269 ++++++++++ src/org/fox/ttrss/offline/OfflineArticlePager.java | 150 ++++++ .../fox/ttrss/offline/OfflineDownloadService.java | 452 ++++++++++++++++ .../offline/OfflineFeedCategoriesFragment.java | 307 +++++++++++ .../fox/ttrss/offline/OfflineFeedsActivity.java | 261 +++++++++ .../fox/ttrss/offline/OfflineFeedsFragment.java | 331 ++++++++++++ .../offline/OfflineHeadlinesEventListener.java | 17 + .../ttrss/offline/OfflineHeadlinesFragment.java | 585 +++++++++++++++++++++ .../fox/ttrss/offline/OfflineUploadService.java | 264 ++++++++++ src/org/fox/ttrss/util/ImageCacheService.java | 208 ++++++++ 19 files changed, 3354 insertions(+), 37 deletions(-) delete mode 100644 src/org/fox/ttrss/ArticleEventListener.java delete mode 100644 src/org/fox/ttrss/FeedsEventListener.java create mode 100644 src/org/fox/ttrss/offline/OfflineActivity.java create mode 100644 src/org/fox/ttrss/offline/OfflineArticleEventListener.java create mode 100644 src/org/fox/ttrss/offline/OfflineArticleFragment.java create mode 100644 src/org/fox/ttrss/offline/OfflineArticlePager.java create mode 100644 src/org/fox/ttrss/offline/OfflineDownloadService.java create mode 100644 src/org/fox/ttrss/offline/OfflineFeedCategoriesFragment.java create mode 100644 src/org/fox/ttrss/offline/OfflineFeedsActivity.java create mode 100644 src/org/fox/ttrss/offline/OfflineFeedsFragment.java create mode 100644 src/org/fox/ttrss/offline/OfflineHeadlinesEventListener.java create mode 100644 src/org/fox/ttrss/offline/OfflineHeadlinesFragment.java create mode 100644 src/org/fox/ttrss/offline/OfflineUploadService.java create mode 100644 src/org/fox/ttrss/util/ImageCacheService.java (limited to 'src/org/fox/ttrss/offline/OfflineFeedsFragment.java') diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 1d48a3be..5b17ba4f 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -47,6 +47,21 @@ android:name=".ArticleActivity" android:label="@string/app_name" > + + + + + + + + + 0; + } + } catch (IllegalStateException e) { + // db is closed? ugh } + + return false; + } + + private boolean hasOfflineData() { + try { + Cursor c = getReadableDb().query("articles", + new String[] { "COUNT(*)" }, null, null, null, null, null); + if (c.moveToFirst()) { + int modified = c.getInt(0); + c.close(); + + return modified > 0; + } + } catch (IllegalStateException e) { + // db is closed? + } + + return false; + } + + @Override + public void onPause() { + super.onPause(); + + unregisterReceiver(m_broadcastReceiver); + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + private void syncOfflineData() { + Log.d(TAG, "offlineSync: starting"); - Log.d(TAG, "m_sessionId=" + m_sessionId); - Log.d(TAG, "m_apiLevel=" + m_apiLevel); + Intent intent = new Intent( + OnlineActivity.this, + OfflineUploadService.class); - setContentView(R.layout.online); + intent.putExtra("sessionId", m_sessionId); + + startService(intent); + } + + private void cancelOfflineSync() { + AlertDialog.Builder builder = new AlertDialog.Builder(this) + .setMessage(R.string.dialog_offline_sync_in_progress) + .setNegativeButton(R.string.dialog_offline_sync_stop, + new Dialog.OnClickListener() { + public void onClick(DialogInterface dialog, + int which) { + + if (m_sessionId != null) { + Log.d(TAG, "offline: stopping"); + + m_offlineModeStatus = 0; + + Intent intent = new Intent( + OnlineActivity.this, + OfflineDownloadService.class); + + stopService(intent); + + dialog.dismiss(); + + restart(); + } + } + }) + .setPositiveButton(R.string.dialog_offline_sync_continue, + new Dialog.OnClickListener() { + public void onClick(DialogInterface dialog, + int which) { + + dialog.dismiss(); + + restart(); + } + }); + + AlertDialog dlg = builder.create(); + dlg.show(); } + + public void restart() { + Intent refresh = new Intent(OnlineActivity.this, OnlineActivity.class); + refresh.putExtra("sessionId", m_sessionId); + refresh.putExtra("apiLevel", m_apiLevel); + startActivity(refresh); + finish(); + } + + private void switchOfflineSuccess() { + logout(); + // setLoadingStatus(R.string.blank, false); + + SharedPreferences.Editor editor = m_prefs.edit(); + editor.putBoolean("offline_mode_active", true); + editor.commit(); + + Intent offline = new Intent(OnlineActivity.this, OfflineActivity.class); + offline.putExtra("initial", true); + offline.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + + startActivityForResult(offline, 0); + finish(); + + } + public void login() { if (m_prefs.getString("ttrss_url", "").trim().length() == 0) { @@ -186,6 +426,9 @@ public class OnlineActivity extends CommonActivity { intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); startActivityForResult(intent, 0); + + if (hasPendingOfflineData()) + syncOfflineData(); finish(); } @@ -203,7 +446,7 @@ public class OnlineActivity extends CommonActivity { login(); return true; case R.id.go_offline: - // FIXME go offline + switchOffline(); return true; case R.id.article_set_note: if (ap != null && ap.getSelectedArticle() != null) { @@ -538,6 +781,30 @@ public class OnlineActivity extends CommonActivity { protected void loginFailure() { m_sessionId = null; initMenu(); + + if (hasOfflineData()) { + + AlertDialog.Builder builder = new AlertDialog.Builder( + OnlineActivity.this) + .setMessage(R.string.dialog_offline_prompt) + .setPositiveButton(R.string.dialog_offline_go, + new Dialog.OnClickListener() { + public void onClick(DialogInterface dialog, + int which) { + switchOfflineSuccess(); + } + }) + .setNegativeButton(R.string.dialog_cancel, + new Dialog.OnClickListener() { + public void onClick(DialogInterface dialog, + int which) { + // + } + }); + + AlertDialog dlg = builder.create(); + dlg.show(); + } } public boolean getUnreadArticlesOnly() { @@ -556,12 +823,20 @@ public class OnlineActivity extends CommonActivity { out.putInt("apiLevel", m_apiLevel); out.putBoolean("unreadOnly", m_unreadOnly); out.putBoolean("unreadArticlesOnly", m_unreadArticlesOnly); + out.putInt("offlineModeStatus", m_offlineModeStatus); } @Override public void onResume() { super.onResume(); + IntentFilter filter = new IntentFilter(); + filter.addAction(OfflineDownloadService.INTENT_ACTION_SUCCESS); + filter.addAction(OfflineUploadService.INTENT_ACTION_SUCCESS); + filter.addCategory(Intent.CATEGORY_DEFAULT); + + registerReceiver(m_broadcastReceiver, filter); + if (m_sessionId == null) { login(); } else { diff --git a/src/org/fox/ttrss/offline/OfflineActivity.java b/src/org/fox/ttrss/offline/OfflineActivity.java new file mode 100644 index 00000000..7fb8c1a9 --- /dev/null +++ b/src/org/fox/ttrss/offline/OfflineActivity.java @@ -0,0 +1,192 @@ +package org.fox.ttrss.offline; + +import org.fox.ttrss.CommonActivity; +import org.fox.ttrss.R; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.provider.BaseColumns; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; + +public class OfflineActivity extends CommonActivity { + private final String TAG = this.getClass().getSimpleName(); + + protected SharedPreferences m_prefs; + protected Menu m_menu; + protected boolean m_unreadOnly; + + @Override + public void onCreate(Bundle savedInstanceState) { + m_prefs = PreferenceManager + .getDefaultSharedPreferences(getApplicationContext()); + + if (m_prefs.getString("theme", "THEME_DARK").equals("THEME_DARK")) { + setTheme(R.style.DarkTheme); + } else { + setTheme(R.style.LightTheme); + } + + super.onCreate(savedInstanceState); + + setContentView(R.layout.online); + + setLoadingStatus(R.string.blank, false); + findViewById(R.id.loading_container).setVisibility(View.GONE); + + initMenu(); + + Intent intent = getIntent(); + + if (intent.getExtras() != null) { + if (intent.getBooleanExtra("initial", false)) { + intent = new Intent(OfflineActivity.this, OfflineFeedsActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + + startActivityForResult(intent, 0); + finish(); + } + } + + if (savedInstanceState != null) { + m_unreadOnly = savedInstanceState.getBoolean("unreadOnly"); + } + } + + @Override + public void onSaveInstanceState(Bundle out) { + super.onSaveInstanceState(out); + + out.putBoolean("unreadOnly", m_unreadOnly); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.go_online: + switchOnline(); + return true; + default: + Log.d(TAG, "onOptionsItemSelected, unhandled id=" + item.getItemId()); + return super.onOptionsItemSelected(item); + } + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.offline_menu, menu); + + m_menu = menu; + + initMenu(); + + return true; + } + + public boolean getUnreadOnly() { + return m_unreadOnly; + } + + protected void initMenu() { + if (m_menu != null) { + m_menu.setGroupVisible(R.id.menu_group_headlines, false); + m_menu.setGroupVisible(R.id.menu_group_headlines_selection, false); + m_menu.setGroupVisible(R.id.menu_group_article, false); + m_menu.setGroupVisible(R.id.menu_group_feeds, false); + } + } + + private void switchOnline() { + SharedPreferences localPrefs = getSharedPreferences("localprefs", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = localPrefs.edit(); + editor.putBoolean("offline_mode_active", false); + editor.commit(); + + Intent refresh = new Intent(this, org.fox.ttrss.OnlineActivity.class); + startActivity(refresh); + finish(); + } + + protected Cursor getArticleById(int articleId) { + Cursor c = getReadableDb().query("articles", null, + BaseColumns._ID + "=?", + new String[] { String.valueOf(articleId) }, null, null, null); + + c.moveToFirst(); + + return c; + } + + protected Cursor getFeedById(int feedId) { + Cursor c = getReadableDb().query("feeds", null, + BaseColumns._ID + "=?", + new String[] { String.valueOf(feedId) }, null, null, null); + + c.moveToFirst(); + + return c; + } + + protected Cursor getCatById(int catId) { + Cursor c = getReadableDb().query("categories", null, + BaseColumns._ID + "=?", + new String[] { String.valueOf(catId) }, null, null, null); + + c.moveToFirst(); + + return c; + } + + protected Intent getShareIntent(Cursor article) { + String title = article.getString(article.getColumnIndex("title")); + String link = article.getString(article.getColumnIndex("link")); + + Intent intent = new Intent(Intent.ACTION_SEND); + + intent.setType("text/plain"); + intent.putExtra(Intent.EXTRA_SUBJECT, title); + intent.putExtra(Intent.EXTRA_TEXT, link); + + return intent; + } + + protected void shareArticle(int articleId) { + + Cursor article = getArticleById(articleId); + + if (article != null) { + shareArticle(article); + article.close(); + } + } + + private void shareArticle(Cursor article) { + if (article != null) { + Intent intent = getShareIntent(article); + + startActivity(Intent.createChooser(intent, + getString(R.id.share_article))); + } + } + + protected int getSelectedArticleCount() { + Cursor c = getReadableDb().query("articles", + new String[] { "COUNT(*)" }, "selected = 1", null, null, null, + null); + c.moveToFirst(); + int selected = c.getInt(0); + c.close(); + + return selected; + } + +} diff --git a/src/org/fox/ttrss/offline/OfflineArticleEventListener.java b/src/org/fox/ttrss/offline/OfflineArticleEventListener.java new file mode 100644 index 00000000..35b9de28 --- /dev/null +++ b/src/org/fox/ttrss/offline/OfflineArticleEventListener.java @@ -0,0 +1,5 @@ +package org.fox.ttrss.offline; + +public interface OfflineArticleEventListener { + +} diff --git a/src/org/fox/ttrss/offline/OfflineArticleFragment.java b/src/org/fox/ttrss/offline/OfflineArticleFragment.java new file mode 100644 index 00000000..266c89b2 --- /dev/null +++ b/src/org/fox/ttrss/offline/OfflineArticleFragment.java @@ -0,0 +1,269 @@ +package org.fox.ttrss.offline; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.fox.ttrss.OnlineActivity; +import org.fox.ttrss.R; +import org.fox.ttrss.util.ImageCacheService; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import android.app.Activity; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.provider.BaseColumns; +import android.support.v4.app.Fragment; +import android.text.Html; +import android.text.method.LinkMovementMethod; +import android.util.Log; +import android.util.TypedValue; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebSettings.LayoutAlgorithm; +import android.widget.TextView; +import android.widget.AdapterView.AdapterContextMenuInfo; + +public class OfflineArticleFragment extends Fragment { + @SuppressWarnings("unused") + private final String TAG = this.getClass().getSimpleName(); + + private SharedPreferences m_prefs; + private int m_articleId; + private boolean m_isCat = false; // FIXME use + private Cursor m_cursor; + private OfflineActivity m_activity; + + public OfflineArticleFragment() { + super(); + } + + public OfflineArticleFragment(int articleId) { + super(); + m_articleId = articleId; + } + + + @Override + public boolean onContextItemSelected(MenuItem item) { + AdapterContextMenuInfo info = (AdapterContextMenuInfo) item + .getMenuInfo(); + + switch (item.getItemId()) { + case R.id.article_link_share: + m_activity.shareArticle(m_articleId); + return true; + case R.id.article_link_copy: + if (true) { + Cursor article = m_activity.getArticleById(m_articleId); + + if (article != null) { + m_activity.copyToClipboard(article.getString(article.getColumnIndex("link"))); + article.close(); + } + } + return true; + default: + Log.d(TAG, "onContextItemSelected, unhandled id=" + item.getItemId()); + return super.onContextItemSelected(item); + } + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + + getActivity().getMenuInflater().inflate(R.menu.article_link_context_menu, menu); + menu.setHeaderTitle(m_cursor.getString(m_cursor.getColumnIndex("title"))); + + super.onCreateContextMenu(menu, v, menuInfo); + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + + if (savedInstanceState != null) { + m_articleId = savedInstanceState.getInt("articleId"); + } + + View view = inflater.inflate(R.layout.article_fragment, container, false); + + m_cursor = m_activity.getReadableDb().query("articles LEFT JOIN feeds ON (feed_id = feeds."+BaseColumns._ID+")", + new String[] { "articles.*", "feeds.title AS feed_title" }, "articles." + BaseColumns._ID + "=?", + new String[] { String.valueOf(m_articleId) }, null, null, null); + + m_cursor.moveToFirst(); + + if (m_cursor.isFirst()) { + + TextView title = (TextView)view.findViewById(R.id.title); + + if (title != null) { + + String titleStr; + + if (m_cursor.getString(m_cursor.getColumnIndex("title")).length() > 200) + titleStr = m_cursor.getString(m_cursor.getColumnIndex("title")).substring(0, 200) + "..."; + else + titleStr = m_cursor.getString(m_cursor.getColumnIndex("title")); + + title.setMovementMethod(LinkMovementMethod.getInstance()); + title.setText(Html.fromHtml("" + titleStr + "")); + registerForContextMenu(title); + } + + WebView web = (WebView)view.findViewById(R.id.content); + + if (web != null) { + + String content; + String cssOverride = ""; + + WebSettings ws = web.getSettings(); + ws.setSupportZoom(true); + ws.setBuiltInZoomControls(true); + + web.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); + + TypedValue tv = new TypedValue(); + getActivity().getTheme().resolveAttribute(R.attr.linkColor, tv, true); + + // prevent flicker in ics + if (android.os.Build.VERSION.SDK_INT >= 11) { + web.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } + + if (m_prefs.getString("theme", "THEME_DARK").equals("THEME_DARK")) { + cssOverride = "body { background : transparent; color : #e0e0e0}"; + //view.setBackgroundColor(android.R.color.black); + web.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + } else { + cssOverride = ""; + } + + String hexColor = String.format("#%06X", (0xFFFFFF & tv.data)); + cssOverride += " a:link {color: "+hexColor+";} a:visited { color: "+hexColor+";}"; + + String articleContent = m_cursor.getString(m_cursor.getColumnIndex("content")); + Document doc = Jsoup.parse(articleContent); + + if (doc != null) { + if (m_prefs.getBoolean("offline_image_cache_enabled", false)) { + + Elements images = doc.select("img"); + + for (Element img : images) { + String url = img.attr("src"); + + if (ImageCacheService.isUrlCached(url)) { + img.attr("src", "file://" + ImageCacheService.getCacheFileName(url)); + } + } + } + + // thanks webview for crashing on