diff options
Diffstat (limited to 'org.fox.ttrss')
16 files changed, 60 insertions, 5833 deletions
diff --git a/org.fox.ttrss/src/main/AndroidManifest.xml b/org.fox.ttrss/src/main/AndroidManifest.xml index b79e3b05..0f66928f 100755 --- a/org.fox.ttrss/src/main/AndroidManifest.xml +++ b/org.fox.ttrss/src/main/AndroidManifest.xml @@ -81,19 +81,6 @@ android:label="@string/logcat_title" > </activity> <activity - android:name=".offline.OfflineActivity" - android:label="@string/app_name" > - </activity> - <activity - android:name=".offline.OfflineMasterActivity" - android:label="@string/app_name" > - </activity> - <activity - android:name=".offline.OfflineDetailActivity" - android:configChanges="keyboardHidden|orientation|screenSize" - android:label="@string/app_name" > - </activity> - <activity android:name=".share.ShareActivity" android:excludeFromRecents="true" android:label="@string/app_name" @@ -209,16 +196,6 @@ </intent-filter> </activity> - <service - android:name=".offline.OfflineDownloadService" - android:enabled="true" /> - <service - android:name=".offline.OfflineUploadService" - android:enabled="true" /> - <service - android:name=".util.ImageCacheService" - android:enabled="true" /> - <meta-data android:name="com.google.android.backup.api_key" android:value="AEdPqrEAAAAIwG6zsGB4qo6ZhjfwIJpm9WI7AqmWaoRXm6ZJnA" /> diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/BaseFeedlistFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/BaseFeedlistFragment.java index 0952e7f7..252b1343 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/BaseFeedlistFragment.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/BaseFeedlistFragment.java @@ -13,8 +13,6 @@ import android.widget.TextView; import androidx.appcompat.widget.SwitchCompat; -import org.fox.ttrss.offline.OfflineActivity; - import java.net.MalformedURLException; import java.net.URL; @@ -23,115 +21,76 @@ public abstract class BaseFeedlistFragment extends androidx.fragment.app.Fragmen public void initDrawerHeader(LayoutInflater inflater, View view, ListView list, final CommonActivity activity, final SharedPreferences prefs, boolean isRoot) { - boolean isOffline = activity instanceof OfflineActivity; - - try { - View layout = inflater.inflate(R.layout.drawer_header, list, false); - list.addHeaderView(layout, null, false); + View layout = inflater.inflate(R.layout.drawer_header, list, false); + list.addHeaderView(layout, null, false); - TextView login = view.findViewById(R.id.drawer_header_login); - TextView server = view.findViewById(R.id.drawer_header_server); + TextView login = view.findViewById(R.id.drawer_header_login); + TextView server = view.findViewById(R.id.drawer_header_server); - login.setText(prefs.getString("login", "")); - try { - server.setText(new URL(prefs.getString("ttrss_url", "")).getHost()); - } catch (MalformedURLException e) { - server.setText(""); - } + login.setText(prefs.getString("login", "")); + try { + server.setText(new URL(prefs.getString("ttrss_url", "")).getHost()); + } catch (MalformedURLException e) { + server.setText(""); + } - View settings = view.findViewById(R.id.drawer_settings_btn); + View settings = view.findViewById(R.id.drawer_settings_btn); - settings.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - try { - Intent intent = new Intent(getActivity(), - PreferencesActivity.class); + settings.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + Intent intent = new Intent(getActivity(), + PreferencesActivity.class); - startActivityForResult(intent, 0); + startActivityForResult(intent, 0); - } catch (Exception e) { - e.printStackTrace(); - } + } catch (Exception e) { + e.printStackTrace(); } - }); - - /* deal with ~material~ footers */ + } + }); - // divider - final View footer = inflater.inflate(R.layout.drawer_divider, list, false); - footer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - // - } - }); - list.addFooterView(footer); - - // unread only checkbox - final View rowToggle = inflater.inflate(R.layout.feeds_row_toggle, list, false); - list.addFooterView(rowToggle); - TextView text = rowToggle.findViewById(R.id.title); - text.setText(R.string.unread_only); - - ImageView icon = rowToggle.findViewById(R.id.icon); - TypedValue tv = new TypedValue(); - getActivity().getTheme().resolveAttribute(R.attr.ic_filter_variant, tv, true); - icon.setImageResource(tv.resourceId); - - final SwitchCompat rowSwitch = rowToggle.findViewById(R.id.row_switch); - rowSwitch.setChecked(activity.getUnreadOnly()); - - rowSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton button, boolean isChecked) { - activity.setUnreadOnly(isChecked); - refresh(); - } - }); + /* deal with ~material~ footers */ - footer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - rowSwitch.setChecked(!rowSwitch.isChecked()); - } - }); - - // root or subdirectory (i.e. feed category) - if (isRoot) { - // offline - final View offlineFooter = inflater.inflate(R.layout.feeds_row, list, false); - offlineFooter.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (activity instanceof OnlineActivity) { - ((OnlineActivity)activity).switchOffline(); - - } else if (activity instanceof OfflineActivity) { - ((OfflineActivity)activity).switchOnline(); - } - } - }); - - list.addFooterView(offlineFooter); - text = offlineFooter.findViewById(R.id.title); - text.setText(isOffline ? R.string.go_online : R.string.go_offline); - - icon = offlineFooter.findViewById(R.id.icon); - tv = new TypedValue(); - getActivity().getTheme().resolveAttribute(isOffline ? R.attr.ic_cloud_upload : R.attr.ic_cloud_download, tv, true); - icon.setImageResource(tv.resourceId); - - TextView counter = offlineFooter.findViewById(R.id.unread_counter); - counter.setText(R.string.blank); + // divider + final View footer = inflater.inflate(R.layout.drawer_divider, list, false); + footer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // } + }); + list.addFooterView(footer); + + // unread only checkbox + final View rowToggle = inflater.inflate(R.layout.feeds_row_toggle, list, false); + list.addFooterView(rowToggle); + TextView text = rowToggle.findViewById(R.id.title); + text.setText(R.string.unread_only); + + ImageView icon = rowToggle.findViewById(R.id.icon); + TypedValue tv = new TypedValue(); + getActivity().getTheme().resolveAttribute(R.attr.ic_filter_variant, tv, true); + icon.setImageResource(tv.resourceId); + + final SwitchCompat rowSwitch = rowToggle.findViewById(R.id.row_switch); + rowSwitch.setChecked(activity.getUnreadOnly()); + + rowSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton button, boolean isChecked) { + activity.setUnreadOnly(isChecked); + refresh(); + } + }); - } catch (InflateException e) { - // welp couldn't inflate header i guess - e.printStackTrace(); - } catch (java.lang.UnsupportedOperationException e) { - e.printStackTrace(); - } + footer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + rowSwitch.setChecked(!rowSwitch.isChecked()); + } + }); } diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/OnlineActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/OnlineActivity.java index ae4622ef..703d131b 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/OnlineActivity.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/OnlineActivity.java @@ -1,15 +1,12 @@ package org.fox.ttrss; import android.annotation.SuppressLint; -import android.annotation.TargetApi; import android.app.Dialog; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnMultiChoiceClickListener; import android.content.Intent; -import android.content.IntentFilter; import android.content.SharedPreferences; import android.graphics.Point; import android.net.ConnectivityManager; @@ -37,15 +34,11 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; -import org.fox.ttrss.offline.OfflineActivity; -import org.fox.ttrss.offline.OfflineDownloadService; -import org.fox.ttrss.offline.OfflineUploadService; import org.fox.ttrss.share.SubscribeActivity; import org.fox.ttrss.types.Article; import org.fox.ttrss.types.ArticleList; import org.fox.ttrss.types.Feed; import org.fox.ttrss.types.Label; -import org.fox.ttrss.util.ImageCacheService; import java.lang.reflect.Type; import java.util.Arrays; @@ -165,17 +158,6 @@ public class OnlineActivity extends CommonActivity { public abstract void OnLoginFailed(); } - private BroadcastReceiver m_broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context content, Intent intent) { - if (intent.getAction().equals(OfflineUploadService.INTENT_ACTION_SUCCESS)) { - toast(R.string.offline_sync_success); - } - } - }; - - - @TargetApi(11) private class HeadlinesActionModeCallback implements ActionMode.Callback { @Override @@ -234,9 +216,6 @@ public class OnlineActivity extends CommonActivity { super.onCreate(savedInstanceState); SharedPreferences localPrefs = getSharedPreferences("localprefs", Context.MODE_PRIVATE); - boolean isOffline = localPrefs.getBoolean("offline_mode_active", false); - - Log.d(TAG, "m_isOffline=" + isOffline); setContentView(R.layout.activity_login); @@ -244,115 +223,9 @@ public class OnlineActivity extends CommonActivity { setSupportActionBar(toolbar); m_cmgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); - - Intent intent = getIntent(); - - Log.d(TAG, "intent action=" + intent.getAction()); - - if (OfflineDownloadService.INTENT_ACTION_CANCEL.equals(intent.getAction())) { - - Intent serviceIntent = new Intent( - OnlineActivity.this, - OfflineDownloadService.class); - - stopService(serviceIntent); - - serviceIntent = new Intent(); - serviceIntent.setAction(ImageCacheService.INTENT_ACTION_ICS_STOP); - serviceIntent.addCategory(Intent.CATEGORY_DEFAULT); - sendBroadcast(serviceIntent); - - } else if (OfflineDownloadService.INTENT_ACTION_SWITCH_OFFLINE.equals(intent.getAction())) { - isOffline = true; - } - - if (isOffline) { - switchOfflineSuccess(); - } else { - m_headlinesActionModeCallback = new HeadlinesActionModeCallback(); - } + m_headlinesActionModeCallback = new HeadlinesActionModeCallback(); } - protected void switchOffline() { - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this) - .setMessage(R.string.dialog_offline_switch_prompt) - .setPositiveButton(R.string.dialog_offline_go, - new Dialog.OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - - if (getSessionId() != null) { - Log.d(TAG, "offline: starting"); - - Intent intent = new Intent( - OnlineActivity.this, - OfflineDownloadService.class); - intent.putExtra("sessionId", getSessionId()); - - startService(intent); - } - } - }) - .setNegativeButton(R.string.dialog_cancel, - new Dialog.OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - // - } - }); - - Dialog dlg = builder.create(); - dlg.show(); - } - - - @Override - public void onPause() { - super.onPause(); - - try { - unregisterReceiver(m_broadcastReceiver); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - } - - private void syncOfflineData() { - Log.d(TAG, "offlineSync: starting"); - - Intent intent = new Intent( - OnlineActivity.this, - OfflineUploadService.class); - - intent.putExtra("sessionId", getSessionId()); - - startService(intent); - } - - private void switchOfflineSuccess() { - logout(); - // setLoadingStatus(R.string.blank, false); - - SharedPreferences localPrefs = getSharedPreferences("localprefs", Context.MODE_PRIVATE); - SharedPreferences.Editor editor = localPrefs.edit(); - editor.putBoolean("offline_mode_active", true); - editor.apply(); - - Intent offline = new Intent(OnlineActivity.this, OfflineActivity.class); - offline.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_CLEAR_TASK | - Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); - offline.putExtra("initial", true); - - startActivity(offline); - - finish(); - } - public void login() { login(false, null); } @@ -415,9 +288,6 @@ public class OnlineActivity extends CommonActivity { startActivityForResult(intent, 0); overridePendingTransition(0, 0); - if (getDatabaseHelper().hasPendingOfflineData()) - syncOfflineData(); - finish(); } @@ -541,15 +411,9 @@ public class OnlineActivity extends CommonActivity { displayAttachments(article); } return true; - /*case R.id.logout: - logout(); - return true;*/ } else if (itemId == R.id.login) { login(); return true; - /*case R.id.go_offline: - switchOffline(); - return true;*/ } else if (itemId == R.id.article_edit_note) { if (ap != null && ap.getSelectedArticle() != null) { editArticleNote(ap.getSelectedArticle()); @@ -1055,42 +919,12 @@ public class OnlineActivity extends CommonActivity { protected void loginFailure() { setSessionId(null); initMenu(); - - if (getDatabaseHelper().hasOfflineData()) { - - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(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) { - // - } - }); - - Dialog dlg = builder.create(); - dlg.show(); - } } @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 (getSessionId() == null) { login(); } else { diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineActivity.java deleted file mode 100755 index 18395778..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineActivity.java +++ /dev/null @@ -1,845 +0,0 @@ -package org.fox.ttrss.offline; - -import android.annotation.SuppressLint; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.content.SharedPreferences; -import android.database.Cursor; -import android.database.sqlite.SQLiteStatement; -import android.net.Uri; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.provider.BaseColumns; -import android.util.Log; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.widget.EditText; - -import androidx.appcompat.view.ActionMode; -import androidx.appcompat.widget.Toolbar; - -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - -import org.fox.ttrss.CommonActivity; -import org.fox.ttrss.OnlineActivity; -import org.fox.ttrss.PreferencesActivity; -import org.fox.ttrss.R; - -public class OfflineActivity extends CommonActivity { - private final String TAG = this.getClass().getSimpleName(); - - protected SharedPreferences m_prefs; - protected Menu m_menu; - - private ActionMode m_headlinesActionMode; - private HeadlinesActionModeCallback m_headlinesActionModeCallback; - - private String m_lastImageHitTestUrl; - - public String getFeedTitle(int feedId, boolean isCat) { - try { - SQLiteStatement stmt; - - if (isCat) { - stmt = getDatabase().compileStatement( - "SELECT title FROM categories " + "WHERE " + BaseColumns._ID + " = ?"); - } else { - stmt = getDatabase().compileStatement( - "SELECT title FROM feeds " + "WHERE " + BaseColumns._ID + " = ?"); - } - - stmt.bindLong(1, feedId); - String title = stmt.simpleQueryForString(); - - stmt.close(); - - return title; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - @SuppressLint("NewApi") - private class HeadlinesActionModeCallback implements ActionMode.Callback { - - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - return false; - } - - @Override - public void onDestroyActionMode(ActionMode mode) { - m_headlinesActionMode = null; - deselectAllArticles(); - } - - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.action_mode_headlines, menu); - - return true; - } - - @Override - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - onOptionsItemSelected(item); - return false; - } - } - - @Override - public boolean onContextItemSelected(android.view.MenuItem item) { - /* AdapterContextMenuInfo info = (AdapterContextMenuInfo) item - .getMenuInfo(); */ - - final OfflineArticlePager ap = (OfflineArticlePager)getSupportFragmentManager().findFragmentByTag(FRAG_ARTICLE); - - int itemId = item.getItemId(); - if (itemId == R.id.article_img_open) { - if (getLastContentImageHitTestUrl() != null) { - try { - openUri(Uri.parse(getLastContentImageHitTestUrl())); - } catch (Exception e) { - e.printStackTrace(); - toast(R.string.error_other_error); - } - } - return true; - } else if (itemId == R.id.article_img_copy) { - if (getLastContentImageHitTestUrl() != null) { - copyToClipboard(getLastContentImageHitTestUrl()); - } - return true; - } else if (itemId == R.id.article_img_share) { - if (getLastContentImageHitTestUrl() != null) { - shareImageFromUri(getLastContentImageHitTestUrl()); - } - return true; - } else if (itemId == R.id.article_img_share_url) { - if (getLastContentImageHitTestUrl() != null) { - shareText(getLastContentImageHitTestUrl()); - } - return true; - } else if (itemId == R.id.article_img_view_caption) { - if (getLastContentImageHitTestUrl() != null) { - - String content = ""; - - Cursor article = getArticleById(ap.getSelectedArticleId()); - - if (article != null) { - content = article.getString(article.getColumnIndex("content")); - article.close(); - } - - displayImageCaption(getLastContentImageHitTestUrl(), content); - } - return true; - } - Log.d(TAG, "onContextItemSelected, unhandled id=" + item.getItemId()); - return super.onContextItemSelected(item); - - } - - @Override - public void onCreate(Bundle savedInstanceState) { - m_prefs = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()); - - setAppTheme(m_prefs); - - super.onCreate(savedInstanceState); - - setContentView(R.layout.activity_login); - - Toolbar toolbar = findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - invalidateOptionsMenu(); - - Intent intent = getIntent(); - - if (intent.getExtras() != null) { - if (intent.getBooleanExtra("initial", false)) { - intent = new Intent(OfflineActivity.this, OfflineMasterActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - - startActivityForResult(intent, 0); - finish(); - } - } - - /* if (savedInstanceState != null) { - - } */ - - m_headlinesActionModeCallback = new HeadlinesActionModeCallback(); - } - - @Override - public void onSaveInstanceState(Bundle out) { - super.onSaveInstanceState(out); - } - - protected void selectArticles(int feedId, boolean isCat, int mode) { - switch (mode) { - case 0: - SQLiteStatement stmtSelectAll = null; - - if (isCat) { - stmtSelectAll = getDatabase().compileStatement( - "UPDATE articles SET selected = 1 WHERE feed_id IN (SELECT "+BaseColumns._ID+" FROM feeds WHERE cat_id = ?)"); - } else { - stmtSelectAll = getDatabase().compileStatement( - "UPDATE articles SET selected = 1 WHERE feed_id = ?"); - } - - stmtSelectAll.bindLong(1, feedId); - stmtSelectAll.execute(); - stmtSelectAll.close(); - - break; - case 1: - - SQLiteStatement stmtSelectUnread = null; - - if (isCat) { - stmtSelectUnread = getDatabase().compileStatement( - "UPDATE articles SET selected = 1 WHERE feed_id IN (SELECT "+BaseColumns._ID+" FROM feeds WHERE cat_id = ?) AND unread = 1"); - } else { - stmtSelectUnread = getDatabase().compileStatement( - "UPDATE articles SET selected = 1 WHERE feed_id = ? AND unread = 1"); - } - - stmtSelectUnread.bindLong(1, feedId); - stmtSelectUnread.execute(); - stmtSelectUnread.close(); - - break; - case 2: - deselectAllArticles(); - break; - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - final OfflineHeadlinesFragment ohf = (OfflineHeadlinesFragment) getSupportFragmentManager() - .findFragmentByTag(FRAG_HEADLINES); - - /* final OfflineFeedsFragment off = (OfflineFeedsFragment) getSupportFragmentManager() - .findFragmentByTag(FRAG_FEEDS); */ - - /* final OfflineFeedCategoriesFragment ocf = (OfflineFeedCategoriesFragment) getSupportFragmentManager() - .findFragmentByTag(FRAG_CATS); */ - - final OfflineArticlePager oap = (OfflineArticlePager) getSupportFragmentManager() - .findFragmentByTag(FRAG_ARTICLE); - - int itemId = item.getItemId();/* case android.R.id.home: - finish(); - return true; *//* case R.id.headlines_toggle_sidebar: - if (true && !isSmallScreen()) { - SharedPreferences.Editor editor = m_prefs.edit(); - editor.putBoolean("headlines_hide_sidebar", !m_prefs.getBoolean("headlines_hide_sidebar", false)); - editor.commit(); - - if (ohf != null && ohf.isAdded()) { - ohf.getView().setVisibility(m_prefs.getBoolean("headlines_hide_sidebar", false) ? View.GONE : View.VISIBLE); - } - } - return true; *//*case R.id.go_online: - switchOnline(); - return true;*/ - if (itemId == R.id.search) { - if (ohf != null) { - Dialog dialog = new Dialog(this); - - final EditText edit = new EditText(this); - - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this) - .setTitle(R.string.search) - .setPositiveButton(getString(R.string.search), - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, - int which) { - - String query = edit.getText().toString().trim(); - - ohf.setSearchQuery(query); - - } - }) - .setNegativeButton(getString(R.string.cancel), - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, - int which) { - - // - - } - }).setView(edit); - - dialog = builder.create(); - dialog.show(); - } - - return true; - } else if (itemId == R.id.preferences) { - Intent intent = new Intent(this, PreferencesActivity.class); - startActivityForResult(intent, 0); - return true; - } else if (itemId == R.id.headlines_view_mode) { - if (ohf != null) { - Dialog dialog = new Dialog(this); - - String viewMode = getViewMode(); - - //Log.d(TAG, "viewMode:" + getViewMode()); - - int selectedIndex = 0; - - if (viewMode.equals("all_articles")) { - selectedIndex = 0; - } else if (viewMode.equals("marked")) { - selectedIndex = 1; - } else if (viewMode.equals("published")) { - selectedIndex = 2; - } else if (viewMode.equals("unread")) { - selectedIndex = 3; - } - - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this) - .setTitle(R.string.headlines_set_view_mode) - .setSingleChoiceItems( - new String[]{ - /* getString(R.string.headlines_adaptive), */ - getString(R.string.headlines_all_articles), - getString(R.string.headlines_starred), - getString(R.string.headlines_published), - getString(R.string.headlines_unread)}, - selectedIndex, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, - int which) { - switch (which) { - /* case 0: - setViewMode("adaptive"); - break; */ - case 0: - setViewMode("all_articles"); - break; - case 1: - setViewMode("marked"); - break; - case 2: - setViewMode("published"); - break; - case 3: - setViewMode("unread"); - break; - } - dialog.cancel(); - - refresh(); - } - }); - - dialog = builder.create(); - dialog.show(); - - } - return true; - } else if (itemId == R.id.headlines_select) { - if (ohf != null) { - - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this) - .setTitle(R.string.headlines_select_dialog) - .setSingleChoiceItems(new String[]{ - getString(R.string.headlines_select_all), - getString(R.string.headlines_select_unread), - getString(R.string.headlines_select_none)}, 0, - new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, - int which) { - - selectArticles(ohf.getFeedId(), ohf.getFeedIsCat(), which); - invalidateOptionsMenu(); - refresh(); - - dialog.cancel(); - } - }); - - Dialog dialog = builder.create(); - dialog.show(); - } - return true; - } else if (itemId == R.id.headlines_mark_as_read) { - if (ohf != null) { - final int feedId = ohf.getFeedId(); - final boolean isCat = ohf.getFeedIsCat(); - - int count = getUnreadArticleCount(feedId, isCat); - - if (count > 0) { - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this) - .setMessage(getResources().getQuantityString(R.plurals.mark_num_headlines_as_read, count, count)) - .setPositiveButton(R.string.catchup, - new OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - - catchupFeed(feedId, isCat); - - } - }) - .setNegativeButton(R.string.dialog_cancel, - new OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - - } - }); - - Dialog dlg = builder.create(); - dlg.show(); - } - } - return true; - } else if (itemId == R.id.share_article) { - int articleId = oap.getSelectedArticleId(); - - shareArticle(articleId); - - return true; - } else if (itemId == R.id.toggle_marked) { - if (oap != null) { - int articleId = oap.getSelectedArticleId(); - - SQLiteStatement stmt = getDatabase().compileStatement( - "UPDATE articles SET modified = 1, modified_marked = 1, marked = NOT marked WHERE " - + BaseColumns._ID + " = ?"); - stmt.bindLong(1, articleId); - stmt.execute(); - stmt.close(); - - refresh(); - } - return true; - } else if (itemId == R.id.toggle_unread) { - if (oap != null) { - int articleId = oap.getSelectedArticleId(); - - SQLiteStatement stmt = getDatabase().compileStatement( - "UPDATE articles SET modified = 1, unread = NOT unread WHERE " - + BaseColumns._ID + " = ?"); - stmt.bindLong(1, articleId); - stmt.execute(); - stmt.close(); - - refresh(); - } - return true; - /* case R.id.selection_select_none: - deselectAllArticles(); - return true; */ - } else if (itemId == R.id.selection_toggle_unread) { - if (getSelectedArticleCount() > 0) { - SQLiteStatement stmt = getDatabase() - .compileStatement( - "UPDATE articles SET modified = 1, unread = NOT unread WHERE selected = 1"); - stmt.execute(); - stmt.close(); - - refresh(); - } - return true; - } else if (itemId == R.id.selection_toggle_marked) { - if (getSelectedArticleCount() > 0) { - SQLiteStatement stmt = getDatabase() - .compileStatement( - "UPDATE articles SET modified = 1, modified_marked = 1, marked = NOT marked WHERE selected = 1"); - stmt.execute(); - stmt.close(); - - refresh(); - } - return true; - } else if (itemId == R.id.selection_toggle_published) { - if (getSelectedArticleCount() > 0) { - SQLiteStatement stmt = getDatabase() - .compileStatement( - "UPDATE articles SET modified = 1, modified_published = 1, published = NOT published WHERE selected = 1"); - stmt.execute(); - stmt.close(); - - refresh(); - } - return true; - } else if (itemId == R.id.toggle_published) { - if (oap != null) { - int articleId = oap.getSelectedArticleId(); - - SQLiteStatement stmt = getDatabase().compileStatement( - "UPDATE articles SET modified = 1, modified_published = 1, published = NOT published WHERE " - + BaseColumns._ID + " = ?"); - stmt.bindLong(1, articleId); - stmt.execute(); - stmt.close(); - - refresh(); - } - return true; - } else if (itemId == R.id.catchup_above) { - if (oap != null) { - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this) - .setMessage(R.string.confirm_catchup_above) - .setPositiveButton(R.string.dialog_ok, - new OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - - catchupAbove(oap); - - } - }) - .setNegativeButton(R.string.dialog_cancel, - new OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - - } - }); - - Dialog dlg = builder.create(); - dlg.show(); - } - return true; - } - Log.d(TAG, "onOptionsItemSelected, unhandled id=" + item.getItemId()); - return super.onOptionsItemSelected(item); - } - - private void catchupAbove(OfflineArticlePager oap) { - int articleId = oap.getSelectedArticleId(); - int feedId = oap.getFeedId(); - boolean isCat = oap.getFeedIsCat(); - - SQLiteStatement stmt = null; - - if (isCat) { - stmt = getDatabase().compileStatement( - "UPDATE articles SET modified = 1, unread = 0 WHERE " + - "updated >= (SELECT updated FROM articles WHERE " + BaseColumns._ID + " = ?) " + - "AND feed_id IN (SELECT "+BaseColumns._ID+" FROM feeds WHERE cat_id = ?)"); - } else { - stmt = getDatabase().compileStatement( - "UPDATE articles SET modified = 1, unread = 0 WHERE " + - "updated >= (SELECT updated FROM articles WHERE " + BaseColumns._ID + " = ?) " + - "AND feed_id = ?"); - } - - stmt.bindLong(1, articleId); - stmt.bindLong(2, feedId); - stmt.execute(); - stmt.close(); - - refresh(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.activity_offline, menu); - - m_menu = menu; - - initMenu(); - - return true; - } - - @SuppressLint("NewApi") - protected void initMenu() { - if (m_menu != null) { - 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_feeds, false); - - OfflineHeadlinesFragment hf = (OfflineHeadlinesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES); - - if (hf != null) { - if (hf.getSelectedArticleCount() > 0 && m_headlinesActionMode == null) { - m_headlinesActionMode = startSupportActionMode(m_headlinesActionModeCallback); - } else if (hf.getSelectedArticleCount() == 0 && m_headlinesActionMode != null) { - m_headlinesActionMode.finish(); - } - } - - OfflineArticlePager ap = (OfflineArticlePager) getSupportFragmentManager().findFragmentByTag(FRAG_ARTICLE); - - if (ap != null) { - int articleId = ap.getSelectedArticleId(); - - Cursor article = getArticleById(articleId); - - if (article != null) { - boolean unread = article.getInt(article.getColumnIndex("unread")) == 1; - boolean marked = article.getInt(article.getColumnIndex("marked")) == 1; - boolean published = article.getInt(article.getColumnIndex("published")) == 1; - - m_menu.findItem(R.id.toggle_marked).setIcon(marked ? R.drawable.baseline_star_24 : - R.drawable.baseline_star_outline_24); - - m_menu.findItem(R.id.toggle_published).setIcon(published ? R.drawable.baseline_check_box_24 : - R.drawable.baseline_rss_feed_24); - - m_menu.findItem(R.id.toggle_unread).setIcon(unread ? R.drawable.baseline_mark_as_unread_24 : - R.drawable.baseline_email_24); - - article.close(); - } - } - } - } - - public void switchOnline() { - SharedPreferences localPrefs = getSharedPreferences("localprefs", Context.MODE_PRIVATE); - SharedPreferences.Editor editor = localPrefs.edit(); - editor.putBoolean("offline_mode_active", false); - editor.apply(); - - Intent refresh = new Intent(this, OnlineActivity.class); - refresh.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_CLEAR_TASK | - Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); - - startActivity(refresh); - - finish(); - } - - protected Cursor getArticleById(int articleId) { - Cursor c = getDatabase().query("articles", null, - BaseColumns._ID + "=?", - new String[]{String.valueOf(articleId)}, null, null, null); - - c.moveToFirst(); - - return c; - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (m_prefs.getBoolean("use_volume_keys", false)) { - OfflineArticlePager ap = (OfflineArticlePager) getSupportFragmentManager().findFragmentByTag(FRAG_ARTICLE); - - if (ap != null && ap.isAdded()) { - switch (keyCode) { - case KeyEvent.KEYCODE_VOLUME_UP: - ap.selectArticle(false); - return true; - case KeyEvent.KEYCODE_VOLUME_DOWN: - ap.selectArticle(true); - return true; - } - } - } - - return super.onKeyDown(keyCode, event); - } - - // Handle onKeyUp too to suppress beep - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - if (m_prefs.getBoolean("use_volume_keys", false)) { - - switch (keyCode) { - case KeyEvent.KEYCODE_VOLUME_UP: - case KeyEvent.KEYCODE_VOLUME_DOWN: - return true; - } - } - - return super.onKeyUp(keyCode, event); - } - - protected Cursor getFeedById(int feedId) { - Cursor c = getDatabase().query("feeds", null, - BaseColumns._ID + "=?", - new String[]{String.valueOf(feedId)}, null, null, null); - - c.moveToFirst(); - - return c; - } - - protected Cursor getCatById(int catId) { - Cursor c = getDatabase().query("categories", null, - BaseColumns._ID + "=?", - new String[]{String.valueOf(catId)}, null, null, null); - - c.moveToFirst(); - - return c; - } - - protected Intent getShareIntent(Cursor article) { - if (article != null) { - String title = article.getString(article.getColumnIndex("title")); - String link = article.getString(article.getColumnIndex("link")); - - return getShareIntent(link, title); - } else { - return null; - } - } - - 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.string.share_article))); - } - } - - protected int getSelectedArticleCount() { - Cursor c = getDatabase().query("articles", - new String[]{"COUNT(*)"}, "selected = 1", null, null, null, - null); - c.moveToFirst(); - int selected = c.getInt(0); - c.close(); - - return selected; - } - - protected int getUnreadArticleCount(int feedId, boolean isCat) { - - Cursor c; - - if (isCat) { - c = getDatabase().query("articles", - new String[] { "COUNT(*)" }, "unread = 1 AND feed_id IN (SELECT "+BaseColumns._ID+" FROM feeds WHERE cat_id = ?)", - new String[] { String.valueOf(feedId) }, - null, null, null); - } else { - c = getDatabase().query("articles", - new String[] { "COUNT(*)" }, "unread = 1 AND feed_id = ?", - new String[] { String.valueOf(feedId) }, - null, null, null); - } - - c.moveToFirst(); - int selected = c.getInt(0); - c.close(); - - return selected; - } - - protected void deselectAllArticles() { - getDatabase().execSQL("UPDATE articles SET selected = 0 "); - refresh(); - } - - protected void refresh() { - OfflineFeedsFragment ff = (OfflineFeedsFragment) getSupportFragmentManager() - .findFragmentByTag(FRAG_FEEDS); - - if (ff != null) { - ff.refresh(); - } - - OfflineFeedCategoriesFragment cf = (OfflineFeedCategoriesFragment) getSupportFragmentManager() - .findFragmentByTag(FRAG_CATS); - - if (cf != null) { - cf.refresh(); - } - - OfflineHeadlinesFragment ohf = (OfflineHeadlinesFragment) getSupportFragmentManager() - .findFragmentByTag(FRAG_HEADLINES); - - if (ohf != null) { - ohf.refresh(); - } - - invalidateOptionsMenu(); - } - - public void catchupFeed(int feedId, boolean isCat) { - if (isCat) { - SQLiteStatement stmt = getDatabase().compileStatement( - "UPDATE articles SET modified = 1, unread = 0 WHERE feed_id IN (SELECT " + - BaseColumns._ID + " FROM feeds WHERE cat_id = ?)"); - stmt.bindLong(1, feedId); - stmt.execute(); - stmt.close(); - } else { - SQLiteStatement stmt = getDatabase().compileStatement( - "UPDATE articles SET modified = 1, unread = 0 WHERE feed_id = ?"); - stmt.bindLong(1, feedId); - stmt.execute(); - stmt.close(); - } - - refresh(); - } - - public void setLastContentImageHitTestUrl(String url) { - m_lastImageHitTestUrl = url; - } - - public String getLastContentImageHitTestUrl() { - return m_lastImageHitTestUrl; - } - - public void setViewMode(String viewMode) { - SharedPreferences.Editor editor = m_prefs.edit(); - editor.putString("offline_view_mode", viewMode); - editor.apply(); - } - - /* public boolean getOldestFirst() { - return getSortMode().equals("oldest_first"); - } - - public String getSortMode() { - return m_prefs.getString("offline_headlines_sort_mode", "default"); - } - - public void setSortMode(String sortMode) { - SharedPreferences.Editor editor = m_prefs.edit(); - editor.putString("offline_headlines_sort_mode", sortMode); - editor.commit(); - } */ - - public String getViewMode() { - return m_prefs.getString("offline_view_mode", "adaptive"); - } - -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineArticleFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineArticleFragment.java deleted file mode 100755 index dfc47131..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineArticleFragment.java +++ /dev/null @@ -1,505 +0,0 @@ -package org.fox.ttrss.offline; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.content.SharedPreferences; -import android.database.Cursor; -import android.graphics.Color; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.provider.BaseColumns; -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.View.OnClickListener; -import android.view.ViewGroup; -import android.webkit.WebChromeClient; -import android.webkit.WebSettings; -import android.webkit.WebView; -import android.webkit.WebView.HitTestResult; -import android.webkit.WebViewClient; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.TextView; - -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 java.net.MalformedURLException; -import java.net.URL; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -import androidx.fragment.app.Fragment; - -import com.google.android.material.button.MaterialButton; - -public class OfflineArticleFragment extends Fragment { - private final String TAG = this.getClass().getSimpleName(); - - private SharedPreferences m_prefs; - private int m_articleId; - private boolean m_isCat = false; // FIXME use - private WebView m_web; - private Cursor m_cursor; - private OfflineDetailActivity m_activity; - - protected View m_customView; - protected FrameLayout m_customViewContainer; - protected View m_contentView; - protected FSVideoChromeClient m_chromeClient; - //protected View m_fab; - - public void initialize(int articleId) { - m_articleId = articleId; - } - - private class FSVideoChromeClient extends WebChromeClient { - //protected View m_videoChildView; - - private CustomViewCallback m_callback; - - public FSVideoChromeClient(View container) { - super(); - - } - - @Override - public void onShowCustomView(View view, CustomViewCallback callback) { - m_activity.getSupportActionBar().hide(); - - // if a view already exists then immediately terminate the new one - if (m_customView != null) { - callback.onCustomViewHidden(); - return; - } - m_customView = view; - m_contentView.setVisibility(View.GONE); - - m_customViewContainer.setVisibility(View.VISIBLE); - m_customViewContainer.addView(view); - - //if (m_fab != null) m_fab.setVisibility(View.GONE); - - m_activity.showSidebar(false); - - m_callback = callback; - } - - @Override - public void onHideCustomView() { - super.onHideCustomView(); - - m_activity.getSupportActionBar().show(); - - if (m_customView == null) - return; - - m_contentView.setVisibility(View.VISIBLE); - m_customViewContainer.setVisibility(View.GONE); - - // Hide the custom view. - m_customView.setVisibility(View.GONE); - - // Remove the custom view from its container. - m_customViewContainer.removeView(m_customView); - m_callback.onCustomViewHidden(); - - /*if (m_fab != null && m_prefs.getBoolean("enable_article_fab", true)) - m_fab.setVisibility(View.VISIBLE);*/ - - m_customView = null; - - m_activity.showSidebar(true); - } - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - /* AdapterContextMenuInfo info = (AdapterContextMenuInfo) item - .getMenuInfo(); */ - - int itemId = item.getItemId(); - if (itemId == R.id.article_link_share) { - m_activity.shareArticle(m_articleId); - return true; - } else if (itemId == 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; - } - 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.context_article_link, menu); - //menu.setHeaderTitle(m_cursor.getString(m_cursor.getColumnIndex("title"))); - - String title = m_cursor.getString(m_cursor.getColumnIndex("title")); - - if (v.getId() == R.id.article_content) { - HitTestResult result = ((WebView)v).getHitTestResult(); - - if (result != null && (result.getType() == HitTestResult.IMAGE_TYPE || result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE)) { - menu.setHeaderTitle(result.getExtra()); - getActivity().getMenuInflater().inflate(R.menu.content_gallery_entry, menu); - - /* FIXME I have no idea how to do this correctly ;( */ - - m_activity.setLastContentImageHitTestUrl(result.getExtra()); - - } else { - menu.setHeaderTitle(title); - getActivity().getMenuInflater().inflate(R.menu.context_article_link, menu); - } - } else { - menu.setHeaderTitle(title); - getActivity().getMenuInflater().inflate(R.menu.context_article_link, menu); - } - - super.onCreateContextMenu(menu, v, menuInfo); - - } - - @SuppressLint("NewApi") - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - - if (savedInstanceState != null) { - m_articleId = savedInstanceState.getInt("articleId"); - } - - View view = inflater.inflate(R.layout.fragment_article, container, false); - - m_cursor = m_activity.getDatabase().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()) { - m_customViewContainer = view.findViewById(R.id.article_fullscreen_video); - - final String link = m_cursor.getString(m_cursor.getColumnIndex("link")); - - int articleFontSize = Integer.parseInt(m_prefs.getString("article_font_size_sp", "16")); - int articleSmallFontSize = Math.max(10, Math.min(18, articleFontSize - 2)); - - TextView title = view.findViewById(R.id.title); - - if (title != null) { - - title.setTextSize(TypedValue.COMPLEX_UNIT_SP, Math.min(21, articleFontSize + 3)); - - 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.setText(titleStr); - //title.setPaintFlags(title.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); - title.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - try { - m_activity.openUri(Uri.parse(link)); - } catch (Exception e) { - e.printStackTrace(); - m_activity.toast(R.string.error_other_error); - } - } - }); - - } - - /* MaterialButton score = view.findViewById(R.id.score); - - if (score != null) { - score.setVisibility(View.GONE); - } - - MaterialButton attachments = view.findViewById(R.id.attachments); - - if (attachments != null) { - attachments.setVisibility(View.GONE); - } - - MaterialButton share = view.findViewById(R.id.share); - - if (share != null) { - share.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - m_activity.shareArticle(m_articleId); - } - }); - } */ - - TextView comments = view.findViewById(R.id.comments); - - if (comments != null) { - comments.setVisibility(View.GONE); - } - - TextView note = view.findViewById(R.id.note); - - if (note != null) { - note.setVisibility(View.GONE); - } - - m_web = view.findViewById(R.id.article_content); - - if (m_web != null) { - - m_web.setWebViewClient(new WebViewClient() { - @Override - public boolean shouldOverrideUrlLoading(WebView view, String url) { - try { - m_activity.openUri(Uri.parse(url)); - - return true; - - } catch (Exception e){ - e.printStackTrace(); - } - - return false; - } }); - - m_web.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - HitTestResult result = ((WebView) v).getHitTestResult(); - - if (result != null && (result.getType() == HitTestResult.IMAGE_TYPE || result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE)) { - registerForContextMenu(m_web); - m_activity.openContextMenu(m_web); - unregisterForContextMenu(m_web); - return true; - } else { - return false; - } - } - }); - - String content; - - WebSettings ws = m_web.getSettings(); - ws.setSupportZoom(false); - ws.setJavaScriptEnabled(false); - - m_chromeClient = new FSVideoChromeClient(getView()); - m_web.setWebChromeClient(m_chromeClient); - m_web.setBackgroundColor(Color.TRANSPARENT); - - ws.setMediaPlaybackRequiresUserGesture(true); - - // we need to show "insecure" file:// urls - if (m_prefs.getBoolean("offline_image_cache_enabled", false) && - android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - - ws.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); - } - - TypedValue tvTextColor = new TypedValue(); - getActivity().getTheme().resolveAttribute(R.attr.colorOnSurface, tvTextColor, true); - - String textColor = String.format("#%06X", (0xFFFFFF & tvTextColor.data)); - - String cssOverride = "body { color : "+textColor+"; }"; - - TypedValue tvColorPrimary = new TypedValue(); - getActivity().getTheme().resolveAttribute(R.attr.colorPrimary, tvColorPrimary, true); - - String linkHexColor = String.format("#%06X", (0xFFFFFF & tvColorPrimary.data)); - cssOverride += " a:link {color: "+linkHexColor+";} a:visited { color: "+linkHexColor+";}"; - - 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,source"); - - for (Element img : images) { - String url = img.attr("src"); - - Log.d(TAG, "src=" + url); - - if (ImageCacheService.isUrlCached(m_activity, url)) { - img.attr("src", "file://" + ImageCacheService.getCacheFileName(m_activity, url)); - } - } - } - - // thanks webview for crashing on <video> tag - /*Elements videos = doc.select("video"); - - for (Element video : videos) - video.remove();*/ - - articleContent = doc.toString(); - } - - if (m_prefs.getBoolean("justify_article_text", true)) { - cssOverride += "body { text-align : justify; } "; - } - - ws.setDefaultFontSize(articleFontSize); - - content = - "<html>" + - "<head>" + - "<meta content=\"text/html; charset=utf-8\" http-equiv=\"content-type\">" + - "<meta name=\"viewport\" content=\"width=device-width, user-scalable=no\" />" + - "<style type=\"text/css\">" + - "body { padding : 0px; margin : 0px; line-height : 130%; }" + - "img,video { max-width : 100%; width : auto; height : auto; }" + - " table { width : 100%; }" + - cssOverride + - "</style>" + - "</head>" + - "<body>" + articleContent; - - content += "</body></html>"; - - try { - String baseUrl = null; - - try { - URL url = new URL(link); - baseUrl = url.getProtocol() + "://" + url.getHost(); - } catch (MalformedURLException e) { - // - } - - m_web.loadDataWithBaseURL(baseUrl, content, "text/html", "utf-8", null); - } catch (RuntimeException e) { - e.printStackTrace(); - } - - - } - - TextView dv = view.findViewById(R.id.date); - - if (dv != null) { - dv.setTextSize(TypedValue.COMPLEX_UNIT_SP, articleSmallFontSize); - - Date d = new Date(m_cursor.getInt(m_cursor.getColumnIndex("updated")) * 1000L); - DateFormat df = new SimpleDateFormat("MMM dd, HH:mm"); - dv.setText(df.format(d)); - } - - TextView tagv = view.findViewById(R.id.tags); - - if (tagv != null) { - tagv.setTextSize(TypedValue.COMPLEX_UNIT_SP, articleSmallFontSize); - - int feedTitleIndex = m_cursor.getColumnIndex("feed_title"); - - if (feedTitleIndex != -1 /* && m_isCat */) { - String fTitle = m_cursor.getString(feedTitleIndex); - - int authorIndex = m_cursor.getColumnIndex("author"); - - if (authorIndex >= 0) { - String authorStr = m_cursor.getString(authorIndex); - - if (authorStr != null && authorStr.length() > 0) { - fTitle += " (" + getString(R.string.author_formatted, m_cursor.getString(authorIndex)) + ")"; - } - } - - tagv.setText(fTitle); - } else { - String tagsStr = m_cursor.getString(m_cursor.getColumnIndex("tags")); - tagv.setText(tagsStr); - } - } - - } - - return view; - } - - @Override - public void onPause() { - super.onPause(); - - if (m_web != null) m_web.onPause(); - } - - public boolean inCustomView() { - return (m_customView != null); - } - - @Override - public void onDestroy() { - super.onDestroy(); - - m_cursor.close(); - } - - public void hideCustomView() { - if (m_chromeClient != null) { - m_chromeClient.onHideCustomView(); - } - } - - @Override - public void onResume() { - super.onResume(); - - if (m_web != null) m_web.onResume(); - } - - @Override - public void onStop() { - super.onStop(); - - if (inCustomView()) { - hideCustomView(); - } - } - @Override - public void onSaveInstanceState (Bundle out) { - super.onSaveInstanceState(out); - - out.putInt("articleId", m_articleId); - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - - m_prefs = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext()); - - m_activity = (OfflineDetailActivity) activity; - - } -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineArticlePager.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineArticlePager.java deleted file mode 100755 index ce4f6f72..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineArticlePager.java +++ /dev/null @@ -1,288 +0,0 @@ -package org.fox.ttrss.offline; - -import android.app.Activity; -import android.content.SharedPreferences; -import android.database.Cursor; -import android.os.Bundle; -import android.os.Parcelable; -import android.preference.PreferenceManager; -import android.provider.BaseColumns; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentStatePagerAdapter; -import androidx.viewpager.widget.ViewPager; - -import org.fox.ttrss.R; - -public class OfflineArticlePager extends Fragment { - private final String TAG = this.getClass().getSimpleName(); - - private PagerAdapter m_adapter; - private OfflineActivity m_activity; - private OfflineHeadlinesEventListener m_listener; - private boolean m_isCat; - private int m_feedId; - private int m_articleId; - private String m_searchQuery = ""; - private Cursor m_cursor; - private SharedPreferences m_prefs; - - public int getFeedId() { - return m_feedId; - } - - public boolean getFeedIsCat() { - return m_isCat; - } - - public Cursor createCursor() { - String feedClause = null; - - if (m_isCat) { - feedClause = "feed_id IN (SELECT "+BaseColumns._ID+" FROM feeds WHERE cat_id = ?)"; - } else { - feedClause = "feed_id = ?"; - } - - String viewMode = m_activity.getViewMode(); - - if ("adaptive".equals(viewMode)) { - // TODO: implement adaptive - } else if ("marked".equals(viewMode)) { - feedClause += "AND (marked = 1)"; - } else if ("published".equals(viewMode)) { - feedClause += "AND (published = 1)"; - } else if ("unread".equals(viewMode)) { - feedClause += "AND (unread = 1)"; - } else { // all_articles - // - } - - String orderBy = (m_prefs.getBoolean("offline_oldest_first", false)) ? "updated" : "updated DESC"; - - if (m_searchQuery == null || m_searchQuery.equals("")) { - return m_activity.getDatabase().query("articles LEFT JOIN feeds ON (feed_id = feeds."+BaseColumns._ID+")", - new String[] { "articles."+BaseColumns._ID, "feeds.title AS feed_title" }, feedClause, - new String[] { String.valueOf(m_feedId) }, null, null, orderBy); - } else { - return m_activity.getDatabase().query("articles LEFT JOIN feeds ON (feed_id = feeds."+BaseColumns._ID+")", - new String[] { "articles."+BaseColumns._ID }, - feedClause + " AND (articles.title LIKE '%' || ? || '%' OR content LIKE '%' || ? || '%')", - new String[] { String.valueOf(m_feedId), m_searchQuery, m_searchQuery }, null, null, orderBy); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - - if (m_cursor != null && !m_cursor.isClosed()) m_cursor.close(); - } - - private class PagerAdapter extends FragmentStatePagerAdapter { - public PagerAdapter(FragmentManager fm) { - super(fm); - } - - // workaround for possible TransactionTooLarge exception on 8.0+ - // we don't need to save member state anyway, bridge takes care of it - @Override - public Parcelable saveState() { - Bundle bundle = (Bundle) super.saveState(); - - if (bundle != null) - bundle.putParcelableArray("states", null); // Never maintain any states from the base class, just null it out - - return bundle; - } - - @Override - public Fragment getItem(int position) { - Log.d(TAG, "getItem: " + position); - - if (m_cursor.moveToPosition(position)) { - - OfflineArticleFragment oaf = new OfflineArticleFragment(); - oaf.initialize(m_cursor.getInt(m_cursor.getColumnIndex(BaseColumns._ID))); - - return oaf; - } - - return null; - } - - @Override - public int getCount() { - return m_cursor.getCount(); - } - } - - @Override - public void onResume() { - super.onResume(); - } - - public void initialize(int articleId, int feedId, boolean isCat) { - m_feedId = feedId; - m_isCat = isCat; - m_articleId = articleId; - - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_article_pager, container, false); - - if (savedInstanceState != null) { - m_articleId = savedInstanceState.getInt("articleId", 0); - m_feedId = savedInstanceState.getInt("feedId", 0); - m_isCat = savedInstanceState.getBoolean("isCat", false); - } - - Log.d(TAG, "feed=" + m_feedId + "; iscat=" + m_isCat); - - m_cursor = createCursor(); - - m_adapter = new PagerAdapter(getActivity().getSupportFragmentManager()); - - int position = 0; - - Log.d(TAG, "maId=" + m_articleId); - - if (m_articleId != 0) { - if (m_cursor.moveToFirst()) { - - while (!m_cursor.isAfterLast()) { - if (m_cursor.getInt(m_cursor.getColumnIndex(BaseColumns._ID)) == m_articleId) { - position = m_cursor.getPosition(); - break; - } - m_cursor.moveToNext(); - } - - Log.d(TAG, "(1)maId=" + m_articleId); - m_listener.onArticleSelected(m_articleId, false); - } - } else { - if (m_cursor.moveToFirst()) { - m_articleId = m_cursor.getInt(m_cursor.getColumnIndex(BaseColumns._ID)); - m_listener.onArticleSelected(m_articleId, false); - - Log.d(TAG, "(2)maId=" + m_articleId); - } - } - - - ViewPager pager = view.findViewById(R.id.article_pager); - - pager.setAdapter(m_adapter); - - pager.setCurrentItem(position); - pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { - @Override - public void onPageScrollStateChanged(int arg0) { - } - - @Override - public void onPageScrolled(int arg0, float arg1, int arg2) { - } - - @Override - public void onPageSelected(int position) { - if (m_cursor.moveToPosition(position)) { - int articleId = m_cursor.getInt(m_cursor.getColumnIndex(BaseColumns._ID)); - - m_articleId = articleId; - m_listener.onArticleSelected(articleId, false); - } - } - }); - - return view; - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - - m_activity = (OfflineActivity)activity; - m_listener = (OfflineHeadlinesEventListener)activity; - - m_prefs = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext()); - - } - - public void refresh() { - if (m_cursor != null && !m_cursor.isClosed()) m_cursor.close(); - - m_cursor = createCursor(); - - if (m_cursor != null) { - m_adapter.notifyDataSetChanged(); - } - } - - public int getSelectedArticleId() { - return m_articleId; - } - - @Override - public void onSaveInstanceState(Bundle out) { - super.onSaveInstanceState(out); - - out.putInt("articleId", m_articleId); - out.putInt("feedId", m_feedId); - out.putBoolean("isCat", m_isCat); - - } - - public void setSearchQuery(String searchQuery) { - m_searchQuery = searchQuery; - } - - public void setArticleId(int articleId) { - m_articleId = articleId; - - int position = getArticleIdPosition(articleId); - - ViewPager pager = getView().findViewById(R.id.article_pager); - - pager.setCurrentItem(position); - - } - - public int getArticleIdPosition(int articleId) { - m_cursor.moveToFirst(); - - while (!m_cursor.isAfterLast()) { - if (m_cursor.getInt(m_cursor.getColumnIndex(BaseColumns._ID)) == articleId) { - return m_cursor.getPosition(); - } - m_cursor.moveToNext(); - } - - return -1; - } - - public void selectArticle(boolean next) { - int position = getArticleIdPosition(m_articleId); - - if (position != -1) { - if (next) - position++; - else - position--; - - Log.d(TAG, "pos=" + position); - - if (m_cursor.moveToPosition(position)) { - setArticleId(m_cursor.getInt(m_cursor.getColumnIndex(BaseColumns._ID))); - } - } - } -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineDetailActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineDetailActivity.java deleted file mode 100755 index 1f8f3dc6..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineDetailActivity.java +++ /dev/null @@ -1,267 +0,0 @@ -package org.fox.ttrss.offline; - -import android.annotation.SuppressLint; -import android.content.Intent; -import android.content.SharedPreferences; -import android.database.Cursor; -import android.database.sqlite.SQLiteStatement; -import android.net.Uri; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.provider.BaseColumns; -import android.util.Log; -import android.view.MenuItem; -import android.view.View; - -import com.google.android.material.floatingactionbutton.FloatingActionButton; - -import org.fox.ttrss.Application; -import org.fox.ttrss.R; - -import androidx.appcompat.app.ActionBarDrawerToggle; -import androidx.appcompat.widget.Toolbar; -import androidx.drawerlayout.widget.DrawerLayout; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentTransaction; - -public class OfflineDetailActivity extends OfflineActivity implements OfflineHeadlinesEventListener { - private final String TAG = this.getClass().getSimpleName(); - - protected SharedPreferences m_prefs; - - private ActionBarDrawerToggle m_drawerToggle; - private DrawerLayout m_drawerLayout; - private int m_activeArticleId; - - @SuppressLint("NewApi") - @Override - public void onCreate(Bundle savedInstanceState) { - m_prefs = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()); - - setAppTheme(m_prefs); - - super.onCreate(savedInstanceState); - - if (m_prefs.getBoolean("force_phone_layout", false)) { - setContentView(R.layout.activity_detail_phone); - } else { - setContentView(R.layout.activity_detail); - } - - Toolbar toolbar = findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - m_drawerLayout = findViewById(R.id.headlines_drawer); - - if (m_drawerLayout != null) { - - m_drawerToggle = new ActionBarDrawerToggle(this, m_drawerLayout, R.string.blank, R.string.blank) { - @Override - public void onDrawerOpened(View drawerView) { - super.onDrawerOpened(drawerView); - - getSupportActionBar().show(); - - invalidateOptionsMenu(); - } - - @Override - public void onDrawerClosed(View drawerView) { - super.onDrawerClosed(drawerView); - - invalidateOptionsMenu(); - } - }; - - m_drawerLayout.addDrawerListener(m_drawerToggle); - m_drawerToggle.setDrawerIndicatorEnabled(true); - - } - - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setHomeButtonEnabled(true); - - setSmallScreen(findViewById(R.id.sw600dp_anchor) == null); - - if (isPortrait()) { - View headlines = findViewById(R.id.headlines_fragment); - - if (headlines != null) - headlines.setVisibility(View.GONE); - } - - if (savedInstanceState == null) { - Intent i = getIntent(); - - if (i.getExtras() != null) { - int feedId = i.getIntExtra("feed", 0); - boolean isCat = i.getBooleanExtra("isCat", false); - int articleId = i.getIntExtra("article", 0); - String searchQuery = i.getStringExtra("searchQuery"); - - OfflineHeadlinesFragment hf = new OfflineHeadlinesFragment(); - hf.initialize(feedId, isCat, true); - - OfflineArticlePager af = new OfflineArticlePager(); - af.initialize(articleId, feedId, isCat); - - hf.setActiveArticleId(articleId); - - hf.setSearchQuery(searchQuery); - af.setSearchQuery(searchQuery); - - FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); - - ft.replace(R.id.headlines_fragment, hf, FRAG_HEADLINES); - ft.replace(R.id.article_fragment, af, FRAG_ARTICLE); - - ft.commit(); - - Cursor c; - - if (isCat) { - c = getCatById(feedId); - } else { - c = getFeedById(feedId); - } - - if (c != null) { - setTitle(c.getString(c.getColumnIndex("title"))); - c.close(); - } - - } - } - - FloatingActionButton fab = findViewById(R.id.detail_fab); - - if (fab != null && m_prefs.getBoolean("enable_article_fab", true)) { - fab.show(); - - fab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (m_activeArticleId != 0) { - Cursor article = getArticleById(m_activeArticleId); - - if (article != null) { - openUri(Uri.parse(article.getString(article.getColumnIndex("link")))); - - article.close(); - } - } - } - }); - } - - } - - protected void onPostCreate(Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); - // Sync the toggle state after onRestoreInstanceState has occurred. - if (m_drawerToggle != null) m_drawerToggle.syncState(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (m_drawerToggle != null && m_drawerToggle.onOptionsItemSelected(item)) { - return true; - } - - if (item.getItemId() == android.R.id.home) { - finish(); - return true; - } - Log.d(TAG, "onOptionsItemSelected, unhandled id=" + item.getItemId()); - return super.onOptionsItemSelected(item); - } - - @Override - public void onArticleSelected(int articleId, boolean open) { - - m_activeArticleId = articleId; - - if (!open) { - SQLiteStatement stmt = getDatabase().compileStatement( - "UPDATE articles SET modified = 1, unread = 0 " + "WHERE " + BaseColumns._ID - + " = ?"); - - stmt.bindLong(1, articleId); - stmt.execute(); - stmt.close(); - } - - if (open) { - if (m_drawerLayout != null) { - m_drawerLayout.closeDrawers(); - } - - OfflineArticlePager af = (OfflineArticlePager) getSupportFragmentManager().findFragmentByTag(FRAG_ARTICLE); - - af.setArticleId(articleId); - } else { - OfflineHeadlinesFragment hf = (OfflineHeadlinesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES); - - hf.setActiveArticleId(articleId); - } - - Application.getInstance().m_selectedArticleId = articleId; - - invalidateOptionsMenu(); - refresh(); - } - - @Override - protected void initMenu() { - super.initMenu(); - - if (m_menu != null) { - m_menu.setGroupVisible(R.id.menu_group_feeds, false); - - //OfflineHeadlinesFragment hf = (OfflineHeadlinesFragment)getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES); - - m_menu.setGroupVisible(R.id.menu_group_headlines, !isPortrait() && !isSmallScreen()); - //m_menu.findItem(R.id.headlines_toggle_sidebar).setVisible(!isPortrait() && !isSmallScreen()); - - Fragment af = getSupportFragmentManager().findFragmentByTag(FRAG_ARTICLE); - - m_menu.setGroupVisible(R.id.menu_group_article, af != null); - - m_menu.findItem(R.id.search).setVisible(false); - } - } - - @Override - public void onArticleSelected(int articleId) { - onArticleSelected(articleId, true); - } - - @Override - public void onBackPressed() { - try { - super.onBackPressed(); - } catch (IllegalStateException e) { - // java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState - e.printStackTrace(); - } - } - - @Override - public void onPause() { - super.onPause(); - - if (isFinishing()) { - overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right); - } - - } - - public void showSidebar(boolean show) { - if (!isSmallScreen() && !isPortrait()) { - findViewById(R.id.headlines_fragment).setVisibility(show ? View.VISIBLE : View.GONE); - invalidateOptionsMenu(); - } - } - -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineDownloadService.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineDownloadService.java deleted file mode 100755 index c3c31133..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineDownloadService.java +++ /dev/null @@ -1,594 +0,0 @@ -package org.fox.ttrss.offline; - -import android.app.ActivityManager; -import android.app.ActivityManager.RunningServiceInfo; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteStatement; -import android.graphics.BitmapFactory; -import android.os.Binder; -import android.os.Build; -import android.os.IBinder; -import android.preference.PreferenceManager; -import android.provider.BaseColumns; -import android.util.Log; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.reflect.TypeToken; - -import org.fox.ttrss.ApiRequest; -import org.fox.ttrss.BuildConfig; -import org.fox.ttrss.CommonActivity; -import org.fox.ttrss.OnlineActivity; -import org.fox.ttrss.R; -import org.fox.ttrss.types.Article; -import org.fox.ttrss.types.Feed; -import org.fox.ttrss.types.FeedCategory; -import org.fox.ttrss.util.DatabaseHelper; -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 java.lang.reflect.Type; -import java.util.HashMap; -import java.util.List; - -import androidx.core.app.NotificationCompat; - -public class OfflineDownloadService extends Service { - - private final String TAG = this.getClass().getSimpleName(); - - // enable downloading read articles in debug configuration for testing - private static boolean OFFLINE_DEBUG_READ = false; - - public static final int NOTIFY_DOWNLOADING = 1; - public static final int NOTIFY_DOWNLOAD_SUCCESS = 2; - - public static final int PI_GENERIC = 0; - public static final int PI_CANCEL = 1; - public static final int PI_SUCCESS = 2; - - //public static final String INTENT_ACTION_SUCCESS = "org.fox.ttrss.intent.action.DownloadComplete"; - public static final String INTENT_ACTION_CANCEL = "org.fox.ttrss.intent.action.Cancel"; - public static final String INTENT_ACTION_SWITCH_OFFLINE = "org.fox.ttrss.intent.action.SwitchOffline"; - - private static final int OFFLINE_SYNC_SEQ = 50; - private static final int OFFLINE_SYNC_MAX = OFFLINE_SYNC_SEQ * 10; - - private int m_articleOffset = 0; - private String m_sessionId; - private NotificationManager m_nmgr; - - private boolean m_batchMode = false; - private boolean m_downloadInProgress = false; - private boolean m_downloadImages = false; - private int m_syncMax; - private SharedPreferences m_prefs; - private boolean m_canProceed = true; - - private final IBinder m_binder = new LocalBinder(); - private DatabaseHelper m_databaseHelper; - - public class LocalBinder extends Binder { - OfflineDownloadService getService() { - return OfflineDownloadService.this; - } - } - - @Override - public IBinder onBind(Intent intent) { - return m_binder; - } - - @Override - public void onCreate() { - super.onCreate(); - m_nmgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - - m_prefs = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()); - - m_downloadImages = m_prefs.getBoolean("offline_image_cache_enabled", false); - m_syncMax = Integer.parseInt(m_prefs.getString("offline_sync_max", String.valueOf(OFFLINE_SYNC_MAX))); - - initDatabase(); - } - - @SuppressWarnings("deprecation") - private void updateNotification(String msg, int progress, int max, boolean showProgress, boolean isError) { - Intent intent = new Intent(this, OnlineActivity.class); - - PendingIntent contentIntent = PendingIntent.getActivity(this, PI_GENERIC, - intent, PendingIntent.FLAG_IMMUTABLE); - - NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext()) - .setContentText(msg) - .setContentTitle(getString(R.string.notify_downloading_title)) - .setContentIntent(contentIntent) - .setWhen(System.currentTimeMillis()) - .setSmallIcon(R.drawable.baseline_cloud_download_24) - .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), - R.drawable.ic_launcher)) - .setOngoing(!isError) - .setOnlyAlertOnce(true); - - if (showProgress) builder.setProgress(max, progress, max == 0); - - intent = new Intent(this, OnlineActivity.class); - intent.setAction(INTENT_ACTION_CANCEL); - - PendingIntent cancelIntent = PendingIntent.getActivity(this, PI_CANCEL, intent, PendingIntent.FLAG_IMMUTABLE); - - builder.setCategory(Notification.CATEGORY_PROGRESS) - .setVibrate(new long[0]) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - .setColor(0x88b0f0) - .setGroup("org.fox.ttrss") - .addAction(R.drawable.ic_launcher, getString(R.string.cancel), cancelIntent); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - builder.setChannelId(CommonActivity.NOTIFICATION_CHANNEL_NORMAL); - } - - m_nmgr.notify(NOTIFY_DOWNLOADING, builder.build()); - } - - @SuppressWarnings("deprecation") - private void notifyDownloadComplete() { - Intent intent = new Intent(this, OnlineActivity.class); - - if (m_articleOffset > 0) { - intent.setAction(INTENT_ACTION_SWITCH_OFFLINE); - } - - PendingIntent contentIntent = PendingIntent.getActivity(this, PI_SUCCESS, - intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - - NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext()) - .setContentIntent(contentIntent) - .setWhen(System.currentTimeMillis()) - .setSmallIcon(R.drawable.ic_notification) - .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), - R.drawable.ic_launcher)) - .setOnlyAlertOnce(true) - .setPriority(Notification.PRIORITY_HIGH) - .setDefaults(Notification.DEFAULT_ALL) - .setAutoCancel(true); - - if (m_articleOffset > 0) { - builder - .setContentTitle(getString(R.string.dialog_offline_success)) - .setContentText(getString(R.string.offline_tap_to_switch)); - } else { - builder - .setContentTitle(getString(R.string.offline_switch_failed)) - .setContentText(getString(R.string.offline_no_articles)); - - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - builder.setCategory(Notification.CATEGORY_MESSAGE) - .setVibrate(new long[0]) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - .setColor(0x88b0f0) - .setGroup("org.fox.ttrss"); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - builder.setChannelId(CommonActivity.NOTIFICATION_CHANNEL_PRIORITY); - } - - m_nmgr.notify(NOTIFY_DOWNLOAD_SUCCESS, builder.build()); - } - - private void updateNotification(int msgResId, int progress, int max, boolean showProgress, boolean isError) { - updateNotification(getString(msgResId), progress, max, showProgress, isError); - } - - private void downloadFailed() { - //m_nmgr.cancel(NOTIFY_DOWNLOADING); - - // TODO send notification to activity? - - m_downloadInProgress = false; - stopSelf(); - } - - private boolean isCacheServiceRunning() { - ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); - for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { - if ("org.fox.ttrss.util.ImageCacheService".equals(service.service.getClassName())) { - return true; - } - } - return false; - } - - public void downloadComplete() { - m_downloadInProgress = false; - - // if cache service is running, it will send a finished intent on its own - if (!isCacheServiceRunning()) { - m_nmgr.cancel(NOTIFY_DOWNLOADING); - - if (m_batchMode) { - - SharedPreferences localPrefs = getSharedPreferences("localprefs", Context.MODE_PRIVATE); - SharedPreferences.Editor editor = localPrefs.edit(); - editor.putBoolean("offline_mode_active", true); - editor.apply(); - - } else { - - /*Intent intent = new Intent(); - intent.setAction(INTENT_ACTION_SUCCESS); - intent.addCategory(Intent.CATEGORY_DEFAULT); - sendBroadcast(intent);*/ - - notifyDownloadComplete(); - } - } - - stopSelf(); - } - - private void initDatabase() { - m_databaseHelper = DatabaseHelper.getInstance(this); - } - - /* private synchronized SQLiteDatabase getReadableDb() { - return m_readableDb; - } */ - - private synchronized SQLiteDatabase getDatabase() { - return m_databaseHelper.getWritableDatabase(); - } - - @SuppressWarnings("unchecked") - private void downloadArticles() { - Log.d(TAG, "offline: downloading articles... offset=" + m_articleOffset); - - updateNotification(getString(R.string.notify_downloading_articles, m_articleOffset), m_articleOffset, m_syncMax, true, false); - - OfflineArticlesRequest req = new OfflineArticlesRequest(this); - - @SuppressWarnings("serial") - HashMap<String,String> map = new HashMap<String,String>(); - map.put("op", "getHeadlines"); - map.put("sid", m_sessionId); - map.put("feed_id", "-4"); - - if (BuildConfig.DEBUG && OFFLINE_DEBUG_READ) { - map.put("view_mode", "all_articles"); - } else { - map.put("view_mode", "unread"); - } - map.put("show_content", "true"); - map.put("skip", String.valueOf(m_articleOffset)); - map.put("limit", String.valueOf(OFFLINE_SYNC_SEQ)); - - req.execute(map); - } - - private void downloadFeeds() { - - updateNotification(R.string.notify_downloading_feeds, 0, 0, true, false); - - getDatabase().execSQL("DELETE FROM feeds;"); - - ApiRequest req = new ApiRequest(getApplicationContext()) { - @Override - protected JsonElement doInBackground(HashMap<String, String>... params) { - JsonElement content = super.doInBackground(params); - - if (content != null) { - - try { - Type listType = new TypeToken<List<Feed>>() {}.getType(); - List<Feed> feeds = new Gson().fromJson(content, listType); - - SQLiteStatement stmtInsert = getDatabase().compileStatement("INSERT INTO feeds " + - "(" + BaseColumns._ID + ", title, feed_url, has_icon, cat_id) " + - "VALUES (?, ?, ?, ?, ?);"); - - for (Feed feed : feeds) { - stmtInsert.bindLong(1, feed.id); - stmtInsert.bindString(2, feed.title); - stmtInsert.bindString(3, feed.feed_url); - stmtInsert.bindLong(4, feed.has_icon ? 1 : 0); - stmtInsert.bindLong(5, feed.cat_id); - - stmtInsert.execute(); - } - - stmtInsert.close(); - - Log.d(TAG, "offline: done downloading feeds"); - - m_articleOffset = 0; - - getDatabase().execSQL("DELETE FROM articles;"); - } catch (Exception e) { - e.printStackTrace(); - updateNotification(getErrorMessage(), 0, 0, false, true); - downloadFailed(); - } - } - - return content; - } - - @Override - protected void onPostExecute(JsonElement content) { - if (content != null) { - if (m_canProceed) { - downloadArticles(); - } else { - downloadFailed(); - } - } else { - updateNotification(getErrorMessage(), 0, 0, false, true); - downloadFailed(); - } - } - - }; - - @SuppressWarnings("serial") - HashMap<String,String> map = new HashMap<String,String>(); - map.put("op", "getFeeds"); - map.put("sid", m_sessionId); - map.put("cat_id", "-3"); - - if (!BuildConfig.DEBUG && OFFLINE_DEBUG_READ) { - map.put("unread_only", "true"); - } - - req.execute(map); - } - - private void downloadCategories() { - - updateNotification(R.string.notify_downloading_categories, 0, 0, true, false); - - getDatabase().execSQL("DELETE FROM categories;"); - - ApiRequest req = new ApiRequest(getApplicationContext()) { - protected JsonElement doInBackground(HashMap<String, String>... params) { - JsonElement content = super.doInBackground(params); - - if (content != null) { - try { - Type listType = new TypeToken<List<FeedCategory>>() {}.getType(); - List<FeedCategory> cats = new Gson().fromJson(content, listType); - - SQLiteStatement stmtInsert = getDatabase().compileStatement("INSERT INTO categories " + - "(" + BaseColumns._ID + ", title) " + - "VALUES (?, ?);"); - - for (FeedCategory cat : cats) { - stmtInsert.bindLong(1, cat.id); - stmtInsert.bindString(2, cat.title); - - stmtInsert.execute(); - } - - stmtInsert.close(); - - Log.d(TAG, "offline: done downloading categories"); - - } catch (Exception e) { - e.printStackTrace(); - updateNotification(getErrorMessage(), 0, 0, false, true); - downloadFailed(); - } - } - - return content; - } - @Override - protected void onPostExecute(JsonElement content) { - if (content != null) { - if (m_canProceed) { - downloadFeeds(); - } else { - downloadFailed(); - } - } else { - updateNotification(getErrorMessage(), 0, 0, false, true); - downloadFailed(); - } - } - - }; - - @SuppressWarnings("serial") - HashMap<String,String> map = new HashMap<String,String>(); - map.put("op", "getCategories"); - map.put("sid", m_sessionId); - //put("cat_id", "-3"); - - if (!BuildConfig.DEBUG && OFFLINE_DEBUG_READ) { - map.put("unread_only", "true"); - } - - req.execute(map); - } - - - @Override - public void onDestroy() { - super.onDestroy(); - m_nmgr.cancel(NOTIFY_DOWNLOADING); - - m_canProceed = false; - Log.d(TAG, "onDestroy"); - - } - - public class OfflineArticlesRequest extends ApiRequest { - List<Article> m_articles; - - public OfflineArticlesRequest(Context context) { - super(context); - } - - @Override - protected JsonElement doInBackground(HashMap<String, String>... params) { - JsonElement content = super.doInBackground(params); - - if (content != null) { - - try { - Type listType = new TypeToken<List<Article>>() {}.getType(); - m_articles = new Gson().fromJson(content, listType); - - SQLiteStatement stmtInsert = getDatabase().compileStatement("INSERT INTO articles " + - "(" + BaseColumns._ID + ", unread, marked, published, score, updated, is_updated, title, link, feed_id, tags, content, author) " + - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); - - for (Article article : m_articles) { - - String tagsString = ""; - - for (String t : article.tags) { - tagsString += t + ", "; - } - - tagsString = tagsString.replaceAll(", $", ""); - - int index = 1; - stmtInsert.bindLong(index++, article.id); - stmtInsert.bindLong(index++, article.unread ? 1 : 0); - stmtInsert.bindLong(index++, article.marked ? 1 : 0); - stmtInsert.bindLong(index++, article.published ? 1 : 0); - stmtInsert.bindLong(index++, article.score); - stmtInsert.bindLong(index++, article.updated); - stmtInsert.bindLong(index++, article.is_updated ? 1 : 0); - stmtInsert.bindString(index++, article.title); - stmtInsert.bindString(index++, article.link); - stmtInsert.bindLong(index++, article.feed_id); - stmtInsert.bindString(index++, tagsString); // comma-separated tags - stmtInsert.bindString(index++, article.content); - stmtInsert.bindString(index++, article.author != null ? article.author : ""); - - if (m_downloadImages) { - Document doc = Jsoup.parse(article.content); - - if (doc != null) { - Elements images = doc.select("img,source"); - - for (Element img : images) { - String url = img.attr("src"); - - if (url.indexOf("://") != -1) { - if (!ImageCacheService.isUrlCached(OfflineDownloadService.this, url)) { - Intent intent = new Intent(OfflineDownloadService.this, - ImageCacheService.class); - - intent.putExtra("url", url); - startService(intent); - } - } - } - - Elements videos = doc.select("video"); - - for (Element vid : videos) { - String url = vid.attr("poster"); - - if (url.indexOf("://") != -1) { - if (!ImageCacheService.isUrlCached(OfflineDownloadService.this, url)) { - Intent intent = new Intent(OfflineDownloadService.this, - ImageCacheService.class); - - intent.putExtra("url", url); - startService(intent); - } - } - } - - } - } - - try { - stmtInsert.execute(); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - m_articleOffset += m_articles.size(); - - Log.d(TAG, "offline: received " + m_articles.size() + " articles; canProc=" + m_canProceed); - - stmtInsert.close(); - - } catch (Exception e) { - updateNotification(R.string.offline_switch_failed, 0, 0, false, true); - Log.d(TAG, "offline: failed: exception when loading articles"); - e.printStackTrace(); - downloadFailed(); - } - - } - - return content; - } - - @Override - protected void onPostExecute(JsonElement content) { - if (content != null) { - - if (m_canProceed && m_articles != null) { - if (m_articles.size() == OFFLINE_SYNC_SEQ && m_articleOffset < m_syncMax) { - downloadArticles(); - } else { - downloadComplete(); - } - } else { - downloadFailed(); - } - - } else { - Log.d(TAG, "offline: failed: " + getErrorMessage()); - updateNotification(getErrorMessage(), 0, 0, false, true); - downloadFailed(); - } - } - } - - @Override - public void onStart(Intent intent, int startId) { - try { - if (getDatabase().isDbLockedByCurrentThread() || getDatabase().isDbLockedByOtherThreads()) { - return; - } - - m_sessionId = intent.getStringExtra("sessionId"); - m_batchMode = intent.getBooleanExtra("batchMode", false); - - if (!m_downloadInProgress) { - if (m_downloadImages) ImageCacheService.cleanupCache(this, false); - - updateNotification(R.string.notify_downloading_init, 0, 0, true, false); - m_downloadInProgress = true; - - downloadCategories(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineFeedCategoriesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineFeedCategoriesFragment.java deleted file mode 100755 index 372728e4..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineFeedCategoriesFragment.java +++ /dev/null @@ -1,358 +0,0 @@ -package org.fox.ttrss.offline; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.database.Cursor; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.provider.BaseColumns; -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.widget.AdapterView; -import android.widget.AdapterView.AdapterContextMenuInfo; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.TextView; - -import org.fox.ttrss.BaseFeedlistFragment; -import org.fox.ttrss.R; - -import androidx.cursoradapter.widget.SimpleCursorAdapter; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - -public class OfflineFeedCategoriesFragment extends BaseFeedlistFragment 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 OfflineMasterActivity m_activity; - private SwipeRefreshLayout m_swipeLayout; - private ListView m_list; - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, - ContextMenuInfo menuInfo) { - - getActivity().getMenuInflater().inflate(R.menu.context_category, menu); - - menu.findItem(R.id.create_shortcut).setEnabled(false); - - AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; - Cursor cursor = getCatAtPosition(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_activity.getUnreadOnly() ? "unread > 0" : "1"); - - String order = m_prefs.getBoolean("sort_feeds_by_unread", false) ? "unread DESC, title" : "title"; - - return m_activity.getDatabase().query("cats_unread", - null, unreadOnly, null, null, null, order); - } - - public void refresh() { - if (!isAdded()) return; - - if (m_swipeLayout != null) m_swipeLayout.setRefreshing(true); - - if (m_cursor != null && !m_cursor.isClosed()) m_cursor.close(); - - m_cursor = createCursor(); - - if (m_cursor != null && m_adapter != null) { - m_adapter.changeCursor(m_cursor); - m_adapter.notifyDataSetChanged(); - if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false); - } - } - - @Override - public void onResume() { - super.onResume(); - refresh(); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - AdapterContextMenuInfo info = (AdapterContextMenuInfo) item - .getMenuInfo(); - - int itemId = item.getItemId(); - if (itemId == R.id.browse_headlines) { - if (true) { - int catId = getCatIdAtPosition(info.position); - if (catId != -10000) { - m_activity.onCatSelected(catId, true); - } - } - return true; - } else if (itemId == R.id.browse_feeds) { - if (true) { - int catId = getCatIdAtPosition(info.position); - if (catId != -10000) { - m_activity.onCatSelected(catId, false); - } - } - return true; - } else if (itemId == R.id.catchup_category) { - if (true) { - int catId = getCatIdAtPosition(info.position); - if (catId != -10000) { - m_activity.catchupFeed(catId, true); - } - } - return true; - } - Log.d(TAG, "onContextItemSelected, unhandled id=" + item.getItemId()); - return super.onContextItemSelected(item); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - - if (savedInstanceState != null) { - m_selectedCatId = savedInstanceState.getInt("selectedFeedId"); - } - - View view = inflater.inflate(R.layout.fragment_feeds, container, false); - - m_swipeLayout = view.findViewById(R.id.feeds_swipe_container); - - m_swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { - @Override - public void onRefresh() { - refresh(); - } - }); - - m_list = 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); - - initDrawerHeader(inflater, view, m_list, m_activity, m_prefs, true); - - m_list.setAdapter(m_adapter); - m_list.setOnItemClickListener(this); - registerForContextMenu(m_list); - - 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_activity = (OfflineMasterActivity)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 = 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_activity.onCatSelected(feedId); - - 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 (!m_activity.isSmallScreen() && 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); - - } - - ImageView icon = v.findViewById(R.id.icon); - - if (icon != null) { - TypedValue tv = new TypedValue(); - - m_activity.getTheme().resolveAttribute(R.attr.ic_folder_outline, tv, true); - icon.setImageResource(tv.resourceId); - - } - - TextView tt = v.findViewById(R.id.title); - - if (tt != null) { - tt.setText(cursor.getString(cursor.getColumnIndex("title"))); - } - - TextView tu = 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); - } - - /*ImageButton ib = (ImageButton) v.findViewById(R.id.feed_menu_button); - - if (ib != null) { - ib.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - getActivity().openContextMenu(v); - } - }); - } */ - - - 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) { - - /* if (m_list != null) { - Cursor c = (Cursor) m_list.getItemAtPosition(position); - - if (c != null) { - int catId = c.getInt(0); - return catId; - } - } */ - - Cursor tmp = getCatAtPosition(position); - - if (tmp != null) { - int id = tmp.getInt(0); - - return id; - } - - return -10000; - } - - public Cursor getCatAtPosition(int position) { - - if (m_list != null) { - return (Cursor) m_list.getItemAtPosition(position); - } - - return null; - } - - public void setSelectedFeedId(int feedId) { - m_selectedCatId = feedId; - refresh(); - } - -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineFeedsFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineFeedsFragment.java deleted file mode 100755 index c0b63330..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineFeedsFragment.java +++ /dev/null @@ -1,367 +0,0 @@ -package org.fox.ttrss.offline; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.database.Cursor; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.util.Log; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.AdapterContextMenuInfo; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ListView; -import android.widget.TextView; - -import org.fox.ttrss.BaseFeedlistFragment; -import org.fox.ttrss.R; - -import androidx.cursoradapter.widget.SimpleCursorAdapter; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - -public class OfflineFeedsFragment extends BaseFeedlistFragment 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 OfflineMasterActivity m_activity; - private SwipeRefreshLayout m_swipeLayout; - private boolean m_enableParentBtn = false; - private ListView m_list; - - public void initialize(int catId, boolean enableParentBtn) { - m_catId = catId; - m_enableParentBtn = enableParentBtn; - } - - @Override - public void onResume() { - super.onResume(); - refresh(); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - AdapterContextMenuInfo info = (AdapterContextMenuInfo) item - .getMenuInfo(); - int itemId = item.getItemId(); - if (itemId == R.id.browse_headlines) { - if (true) { - int feedId = getFeedIdAtPosition(info.position); - if (feedId != -10000) { - m_activity.onFeedSelected(feedId); - } - } - return true; - } else if (itemId == R.id.catchup_feed) { - int feedId = getFeedIdAtPosition(info.position); - if (feedId != -10000) { - m_activity.catchupFeed(feedId, false); - } - return true; - } - 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.context_feed, menu); - - menu.findItem(R.id.create_shortcut).setEnabled(false); - - AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; - Cursor cursor = getFeedAtPosition(info.position); - - if (cursor != null) - menu.setHeaderTitle(cursor.getString(cursor.getColumnIndex("title"))); - - super.onCreateContextMenu(menu, v, menuInfo); - - } - - public Cursor createCursor() { - String unreadOnly = m_activity.getUnreadOnly() ? "unread > 0" : "1"; - String order = m_prefs.getBoolean("sort_feeds_by_unread", false) ? "unread DESC, title" : "title"; - - if (m_catId != -1) { - return m_activity.getDatabase().query("feeds_unread", - null, unreadOnly + " AND cat_id = ?", new String[] { String.valueOf(m_catId) }, null, null, order); - } else { - return m_activity.getDatabase().query("feeds_unread", - null, unreadOnly, null, null, null, order); - } - } - - public void refresh() { - try { - if (!isAdded()) return; - - if (m_swipeLayout != null) m_swipeLayout.setRefreshing(true); - - if (m_cursor != null && !m_cursor.isClosed()) m_cursor.close(); - - m_cursor = createCursor(); - - if (m_cursor != null && m_adapter != null) { - m_adapter.changeCursor(m_cursor); - m_adapter.notifyDataSetChanged(); - if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false); - } - } catch (NullPointerException e) { - e.printStackTrace(); - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - - if (savedInstanceState != null) { - m_selectedFeedId = savedInstanceState.getInt("selectedFeedId"); - m_catId = savedInstanceState.getInt("catId"); - m_enableParentBtn = savedInstanceState.getBoolean("enableParentBtn"); - } - - View view = inflater.inflate(R.layout.fragment_feeds, container, false); - - m_swipeLayout = view.findViewById(R.id.feeds_swipe_container); - - m_swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { - @Override - public void onRefresh() { - refresh(); - } - }); - - m_list = view.findViewById(R.id.feeds); - - initDrawerHeader(inflater, view, m_list, m_activity, m_prefs, !m_enableParentBtn); - - if (m_enableParentBtn) { - View layout = inflater.inflate(R.layout.feeds_goback, container, false); - - layout.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, - ListView.LayoutParams.WRAP_CONTENT)); - - layout.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - m_activity.getSupportFragmentManager().popBackStack(); - } - }); - - m_list.addHeaderView(layout, null, false); - } - - 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); - - m_list.setAdapter(m_adapter); - m_list.setOnItemClickListener(this); - registerForContextMenu(m_list); - - 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_activity = (OfflineMasterActivity)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); - out.putBoolean("enableParentBtn", m_enableParentBtn); - } - - @Override - public void onItemClick(AdapterView<?> av, View view, int position, long id) { - ListView list = 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_activity.onFeedSelected(feedId); - - m_selectedFeedId = feedId; - - m_adapter.notifyDataSetChanged(); - } - } - } - - 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 boolean isEmpty() { - return !m_enableParentBtn && super.isEmpty(); - } - - @Override - public int getItemViewType(int position) { - Cursor cursor = (Cursor) this.getItem(position); - - if (!m_activity.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 = v.findViewById(R.id.title); - - if (tt != null) { - tt.setText(cursor.getString(cursor.getColumnIndex("title"))); - } - - TextView tu = 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); - } - - /*ImageButton ib = (ImageButton) v.findViewById(R.id.feed_menu_button); - - if (ib != null) { - ib.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - getActivity().openContextMenu(v); - } - }); - }*/ - - 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) { - /* if (m_list != null) { - Cursor c = (Cursor) m_list.getItemAtPosition(position); - - if (c != null) { - int feedId = c.getInt(0); - return feedId; - } - } */ - - Cursor tmp = getFeedAtPosition(position); - - if (tmp != null) { - int id = tmp.getInt(0); - - return id; - } - - return -10000; - } - - public Cursor getFeedAtPosition(int position) { - - if (m_list != null) { - return (Cursor) m_list.getItemAtPosition(position); - } - - return null; - } - - public void setSelectedFeedId(int feedId) { - m_selectedFeedId = feedId; - refresh(); - } - -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesEventListener.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesEventListener.java deleted file mode 100644 index 0818a66b..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesEventListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.fox.ttrss.offline; - - -public interface OfflineHeadlinesEventListener { - void onArticleSelected(int articleId, boolean open); - void onArticleSelected(int articleId); -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesFragment.java deleted file mode 100755 index 0f1509fa..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesFragment.java +++ /dev/null @@ -1,1311 +0,0 @@ -package org.fox.ttrss.offline; - -import android.app.Activity; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.ColorStateList; -import android.database.Cursor; -import android.database.sqlite.SQLiteStatement; -import android.graphics.Paint; -import android.graphics.Point; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.provider.BaseColumns; -import android.text.Html; -import android.util.Log; -import android.util.TypedValue; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.Display; -import android.view.LayoutInflater; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.WindowManager; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.AdapterView.AdapterContextMenuInfo; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.CheckBox; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.PopupMenu; -import android.widget.ProgressBar; -import android.widget.TextView; - -import com.amulyakhare.textdrawable.TextDrawable; -import com.amulyakhare.textdrawable.util.ColorGenerator; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; -import com.bumptech.glide.load.resource.drawable.GlideDrawable; -import com.bumptech.glide.request.RequestListener; -import com.bumptech.glide.request.target.Target; -import com.google.android.material.button.MaterialButton; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - -import org.fox.ttrss.Application; -import org.fox.ttrss.CommonActivity; -import org.fox.ttrss.GalleryActivity; -import org.fox.ttrss.HeadlinesFragment; -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 java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.TimeZone; - -import androidx.core.app.ActivityCompat; -import androidx.core.app.ActivityOptionsCompat; -import androidx.core.view.ViewCompat; -import androidx.cursoradapter.widget.SimpleCursorAdapter; -import androidx.fragment.app.Fragment; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import jp.wasabeef.glide.transformations.CropCircleTransformation; - -public class OfflineHeadlinesFragment extends Fragment implements OnItemClickListener, AbsListView.OnScrollListener { - public enum ArticlesSelection { ALL, NONE, UNREAD } - - private final String TAG = this.getClass().getSimpleName(); - - private int m_feedId; - private boolean m_feedIsCat = false; - private String m_feedTitle; - - private int m_activeArticleId; - private String m_searchQuery = ""; - - private SharedPreferences m_prefs; - private ArrayList<Integer> m_readArticleIds = new ArrayList<Integer>(); - private ArrayList<Integer> m_autoMarkedArticleIds = new ArrayList<Integer>(); - - private HashMap<Integer, Integer> m_flavorHeightStorage = new HashMap<>(); - - private Cursor m_cursor; - private ArticleListAdapter m_adapter; - - private OfflineHeadlinesEventListener m_listener; - private OfflineActivity m_activity; - private SwipeRefreshLayout m_swipeLayout; - - private boolean m_compactLayoutMode = false; - private ListView m_list; - - public void initialize(int feedId, boolean isCat, boolean compactMode) { - m_feedId = feedId; - m_feedIsCat = isCat; - m_compactLayoutMode = compactMode; - } - - @Override - public void onDestroy() { - super.onDestroy(); - - if (m_cursor != null && !m_cursor.isClosed()) m_cursor.close(); - } - - public int getSelectedArticleCount() { - Cursor c = m_activity.getDatabase().query("articles", - new String[] { "COUNT(*)" }, "selected = 1", null, null, null, null); - c.moveToFirst(); - int selected = c.getInt(0); - c.close(); - - return selected; - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, - ContextMenuInfo menuInfo) { - - getActivity().getMenuInflater().inflate(R.menu.context_headlines, menu); - - menu.findItem(R.id.article_set_labels).setVisible(false); - menu.findItem(R.id.article_edit_note).setVisible(false); - - if (m_prefs.getBoolean("offline_sort_by_feed", false)) { - menu.findItem(R.id.catchup_above).setVisible(false); - } - - super.onCreateContextMenu(menu, v, menuInfo); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - AdapterContextMenuInfo info = (AdapterContextMenuInfo) item - .getMenuInfo(); - - int articleId = getArticleIdAtPosition(info.position); - - if (!onArticleMenuItemSelected(item, articleId)) - return super.onContextItemSelected(item); - else - return true; - } - - private boolean onArticleMenuItemSelected(MenuItem item, final int articleId) { - int itemId = item.getItemId(); - if (itemId == R.id.headlines_article_unread) { - if (true) { - - SQLiteStatement stmt = m_activity.getDatabase().compileStatement( - "UPDATE articles SET modified = 1, unread = not unread " + "WHERE " + BaseColumns._ID - + " = ?"); - - stmt.bindLong(1, articleId); - stmt.execute(); - stmt.close(); - - refresh(); - } - return true; - } else if (itemId == R.id.headlines_article_link_copy) { - if (true) { - Cursor article = m_activity.getArticleById(articleId); - - if (article != null) { - m_activity.copyToClipboard(article.getString(article.getColumnIndex("link"))); - article.close(); - } - } - return true; - } else if (itemId == R.id.headlines_article_link_open) { - if (true) { - Cursor article = m_activity.getArticleById(articleId); - - if (article != null) { - m_activity.openUri(Uri.parse(article.getString(article.getColumnIndex("link")))); - - // TODO: mark article as read, set modified = 1, refresh - - article.close(); - } - } - return true; - } else if (itemId == R.id.headlines_share_article) { - m_activity.shareArticle(articleId); - return true; - } else if (itemId == R.id.catchup_above) { - if (true) { - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext()) - .setMessage(R.string.confirm_catchup_above) - .setPositiveButton(R.string.dialog_ok, - new Dialog.OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - - catchupAbove(articleId); - - } - }) - .setNegativeButton(R.string.dialog_cancel, - new Dialog.OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - - } - }); - - Dialog dialog = builder.create(); - dialog.show(); - } - return true; - } - Log.d(TAG, "onArticleMenuItemSelected, unhandled id=" + item.getItemId()); - return false; - - } - - private void catchupAbove(int articleId) { - SQLiteStatement stmt = null; - - String updatedOperator = (m_prefs.getBoolean("offline_oldest_first", false)) ? "<" : ">"; - - if (m_feedIsCat) { - stmt = m_activity.getDatabase().compileStatement( - "UPDATE articles SET modified = 1, unread = 0 WHERE " + - "updated "+updatedOperator+" (SELECT updated FROM articles WHERE " + BaseColumns._ID + " = ?) " + - "AND unread = 1 AND feed_id IN (SELECT "+BaseColumns._ID+" FROM feeds WHERE cat_id = ?)"); - } else { - stmt = m_activity.getDatabase().compileStatement( - "UPDATE articles SET modified = 1, unread = 0 WHERE " + - "updated "+updatedOperator+" (SELECT updated FROM articles WHERE " + BaseColumns._ID + " = ?) " + - "AND unread = 1 AND feed_id = ?"); - } - - stmt.bindLong(1, articleId); - stmt.bindLong(2, m_feedId); - stmt.execute(); - stmt.close(); - - refresh(); - } - - @Override - public void onResume() { - super.onResume(); - - if (Application.getInstance().m_selectedArticleId != 0) { - m_activeArticleId = Application.getInstance().m_selectedArticleId; - Application.getInstance().m_selectedArticleId = 0; - } - - if (m_activeArticleId != 0) { - setActiveArticleId(m_activeArticleId); - } - - //refresh(); - - m_activity.invalidateOptionsMenu(); - } - - public void refresh() { - refresh(true); - } - - public void refresh(boolean keepRemnantIds) { - try { - if (!isAdded()) return; - - if (m_swipeLayout != null) m_swipeLayout.setRefreshing(true); - - if (m_cursor != null && !m_cursor.isClosed()) m_cursor.close(); - - if (!keepRemnantIds) m_autoMarkedArticleIds.clear(); - - m_cursor = createCursor(); - - if (m_cursor != null && m_adapter != null) { - m_adapter.changeCursor(m_cursor); - m_adapter.notifyDataSetChanged(); - } - - if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false); - - } catch (NullPointerException e) { - e.printStackTrace(); - } - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setRetainInstance(true); - - Glide.get(getContext()).clearMemory(); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - - if (savedInstanceState != null) { - m_feedId = savedInstanceState.getInt("feedId"); - m_activeArticleId = savedInstanceState.getInt("activeArticleId"); - //m_selectedArticles = savedInstanceState.getParcelableArrayList("selectedArticles"); - m_searchQuery = (String) savedInstanceState.getCharSequence("searchQuery"); - m_feedIsCat = savedInstanceState.getBoolean("feedIsCat"); - m_compactLayoutMode = savedInstanceState.getBoolean("compactLayoutMode"); - m_readArticleIds = savedInstanceState.getIntegerArrayList("autoMarkedIds"); - - } else { - m_activity.getDatabase().execSQL("UPDATE articles SET selected = 0 "); - } - - String headlineMode = m_prefs.getString("headline_mode", "HL_DEFAULT"); - - if ("HL_COMPACT".equals(headlineMode) || "HL_COMPACT_NOIMAGES".equals(headlineMode)) - m_compactLayoutMode = true; - - View view = inflater.inflate(R.layout.fragment_headlines_offline, container, false); - - m_swipeLayout = view.findViewById(R.id.headlines_swipe_container); - - m_swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { - @Override - public void onRefresh() { - refresh(false); - } - }); - - m_cursor = createCursor(); - - m_list = view.findViewById(R.id.headlines_list); - - if (m_prefs.getBoolean("headlines_mark_read_scroll", false)) { - WindowManager wm = (WindowManager) m_activity.getSystemService(Context.WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - int screenHeight = (int)(display.getHeight() * 1.5); - - View layout = inflater.inflate(R.layout.headlines_footer, container, false); - - layout.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, screenHeight)); - - m_list.addFooterView(layout, null, false); - } - - - m_adapter = new ArticleListAdapter(getActivity(), R.layout.headlines_row, m_cursor, - new String[] { "title" }, new int[] { R.id.title }, 0); - m_list.setAdapter(m_adapter); - - m_list.setOnItemClickListener(this); - m_list.setOnScrollListener(this); - registerForContextMenu(m_list); - - m_feedTitle = m_activity.getFeedTitle(m_feedId, m_feedIsCat); - - if (m_feedTitle != null && m_activity.isSmallScreen()) { - m_activity.setTitle(m_feedTitle); - } - - return view; - } - - 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 = ?"; - } - - String viewMode = m_activity.getViewMode(); - - if ("adaptive".equals(viewMode)) { - // TODO: implement adaptive - } else if ("marked".equals(viewMode)) { - feedClause += "AND (marked = 1)"; - } else if ("published".equals(viewMode)) { - feedClause += "AND (published = 1)"; - } else if ("unread".equals(viewMode)) { - String idsMarkedRead = "articles." + BaseColumns._ID + " in (" + android.text.TextUtils.join(",", m_autoMarkedArticleIds) + ")"; - - feedClause += "AND (unread = 1 OR "+idsMarkedRead+")"; - } else { // all_articles - // - } - - String orderBy = (m_prefs.getBoolean("offline_oldest_first", false)) ? "updated" : "updated DESC"; - - if (m_prefs.getBoolean("offline_sort_by_feed", false)) { - orderBy = "feed_title, " + orderBy; - } - - if (m_searchQuery == null || m_searchQuery.equals("")) { - return m_activity.getDatabase().query("articles LEFT JOIN feeds ON (feed_id = feeds."+BaseColumns._ID+")", - new String[] { "articles.*", "feeds.title AS feed_title" }, feedClause, - new String[] { String.valueOf(m_feedId) }, null, null, orderBy); - } else { - return m_activity.getDatabase().query("articles LEFT JOIN feeds ON (feed_id = feeds."+BaseColumns._ID+")", - new String[] { "articles.*", "feeds.title AS feed_title" }, - feedClause + " AND (articles.title LIKE '%' || ? || '%' OR content LIKE '%' || ? || '%')", - new String[] { String.valueOf(m_feedId), m_searchQuery, m_searchQuery }, null, null, orderBy); - } - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - m_listener = (OfflineHeadlinesEventListener) activity; - m_activity = (OfflineActivity) activity; - - m_prefs = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext()); - } - - @Override - public void onItemClick(AdapterView<?> av, View view, int position, long id) { - ListView list = (ListView)av; - - Log.d(TAG, "onItemClick=" + position); - - if (list != null) { - - int articleId = getArticleIdAtPosition(position); - - if (articleId != 0) { - - if (getActivity().findViewById(R.id.article_fragment) != null) { - m_activeArticleId = articleId; - } - - m_listener.onArticleSelected(articleId); - - refresh(); - } - } - } - - @Override - public void onSaveInstanceState (Bundle out) { - super.onSaveInstanceState(out); - - out.putInt("feedId", m_feedId); - out.putInt("activeArticleId", m_activeArticleId); - //out.putParcelableArrayList("selectedArticles", m_selectedArticles); - out.putCharSequence("searchQuery", m_searchQuery); - out.putBoolean("feedIsCat", m_feedIsCat); - out.putIntegerArrayList("autoMarkedIds", m_autoMarkedArticleIds); - - out.putBoolean("compactLayoutMode", m_compactLayoutMode); - } - - /* 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); - } */ - - static class ArticleViewHolder { - - public int articleId; - HashMap<Integer, Integer> flavorHeightStorage; - - public View view; - - public TextView titleView; - public TextView feedTitleView; - public MaterialButton markedView; - public MaterialButton publishedView; - public TextView excerptView; - public ImageView flavorImageView; - public TextView authorView; - public TextView dateView; - public CheckBox selectionBoxView; - public MaterialButton menuButtonView; - public ViewGroup flavorImageHolder; - public ProgressBar flavorImageLoadingBar; - public View headlineFooter; - public ImageView textImage; - public ImageView textChecked; - public ImageView flavorVideoKindView; - public View flavorImageOverflow; - public View headlineHeader; - public MaterialButton attachmentsView; - public MaterialButton scoreView; - - public ArticleViewHolder(View v) { - - view = v; - - view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - View flavorImage = view.findViewById(R.id.flavor_image); - - if (flavorImage != null) { - int height = flavorImage.getMeasuredHeight(); - - if (height > 0) { - //Log.d("ArticleViewHolder", "view measured height: " + flavorImage.getMeasuredHeight() + " for " + articleId); - - flavorHeightStorage.put(articleId, flavorImage.getMeasuredHeight()); - } - } - - return true; - } - }); - - titleView = v.findViewById(R.id.title); - - feedTitleView = v.findViewById(R.id.feed_title); - markedView = v.findViewById(R.id.marked); - publishedView = v.findViewById(R.id.published); - excerptView = v.findViewById(R.id.excerpt); - flavorImageView = v.findViewById(R.id.flavor_image); - authorView = v.findViewById(R.id.author); - dateView = v.findViewById(R.id.date); - selectionBoxView = v.findViewById(R.id.selected); - menuButtonView = v.findViewById(R.id.article_menu_button); - flavorImageHolder = v.findViewById(R.id.flavorImageHolder); - flavorImageLoadingBar = v.findViewById(R.id.flavorImageLoadingBar); - headlineFooter = v.findViewById(R.id.headline_footer); - textImage = v.findViewById(R.id.text_image); - textChecked = v.findViewById(R.id.text_checked); - flavorVideoKindView = v.findViewById(R.id.flavor_video_kind); - headlineHeader = v.findViewById(R.id.headline_header); - flavorImageOverflow = v.findViewById(R.id.gallery_overflow); - attachmentsView = v.findViewById(R.id.attachments); - scoreView = v.findViewById(R.id.score); - } - } - - private class ArticleListAdapter extends SimpleCursorAdapter { - public static final int VIEW_NORMAL = 0; - public static final int VIEW_UNREAD = 1; - public static final int VIEW_SELECTED = 2; - public static final int VIEW_SELECTED_UNREAD = 3; - public static final int VIEW_LOADMORE = 4; - - public static final int VIEW_COUNT = VIEW_LOADMORE+1; - - private final Integer[] origTitleColors = new Integer[VIEW_COUNT]; - - private ColorGenerator m_colorGenerator = ColorGenerator.DEFAULT; - private TextDrawable.IBuilder m_drawableBuilder = TextDrawable.builder().round(); - - private boolean showFlavorImage; - private int m_screenHeight; - - public ArticleListAdapter(Context context, int layout, Cursor c, - String[] from, int[] to, int flags) { - super(context, layout, c, from, to, flags); - - String headlineMode = m_prefs.getString("headline_mode", "HL_DEFAULT"); - showFlavorImage = "HL_DEFAULT".equals(headlineMode) || "HL_COMPACT".equals(headlineMode); - - Display display = m_activity.getWindowManager().getDefaultDisplay(); - Point size = new Point(); - display.getSize(size); - //m_minimumHeightToEmbed = size.y/3; - m_screenHeight = size.y; - } - - public int getViewTypeCount() { - return VIEW_COUNT; - } - - @Override - public int getItemViewType(int position) { - Cursor c = (Cursor) getItem(position); - - //Log.d(TAG, "@gIVT " + position + " " + c.getInt(0) + " vs " + m_activeArticleId); - - if (c.getInt(0) == m_activeArticleId && c.getInt(c.getColumnIndex("unread")) == 1) { - return VIEW_SELECTED_UNREAD; - } else if (c.getInt(0) == m_activeArticleId) { - return VIEW_SELECTED; - } else if (c.getInt(c.getColumnIndex("unread")) == 1) { - return VIEW_UNREAD; - } else { - return VIEW_NORMAL; - } - } - - private void updateTextCheckedState(ArticleViewHolder holder, Cursor item, ArticleFlavorInfo afi) { - String title = item.getString(item.getColumnIndex("title")); - - String tmp = title.length() > 0 ? title.substring(0, 1) : "?"; - - boolean isChecked = item.getInt(item.getColumnIndex("selected")) == 1; - - if (isChecked) { - holder.textImage.setImageDrawable(m_drawableBuilder.build(" ", 0xff616161)); - - holder.textChecked.setVisibility(View.VISIBLE); - } else { - Drawable textDrawable = m_drawableBuilder.build(tmp, m_colorGenerator.getColor(title)); - - if (showFlavorImage && afi.flavorImageUri != null) { - - holder.textImage.setImageDrawable(textDrawable); - - Glide.with(getContext()) - .load(afi.flavorImageUri) - .placeholder(textDrawable) - .bitmapTransform(new CropCircleTransformation(getActivity())) - .diskCacheStrategy(DiskCacheStrategy.NONE) - .skipMemoryCache(false) - .listener(new RequestListener<String, GlideDrawable>() { - @Override - public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) { - return false; - } - - @Override - public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) { - - return resource.getIntrinsicWidth() < HeadlinesFragment.THUMB_IMG_MIN_SIZE || - resource.getIntrinsicHeight() < HeadlinesFragment.THUMB_IMG_MIN_SIZE; - } - }) - .into(holder.textImage); - - } else { - holder.textImage.setImageDrawable(textDrawable); - } - - holder.textChecked.setVisibility(View.GONE); - } - } - - @Override - public View getView(int position, final View convertView, ViewGroup parent) { - - View v = convertView; - - final Cursor article = (Cursor)getItem(position); - - final ArticleViewHolder holder; - - final int articleId = article.getInt(0); - - int headlineFontSize = m_prefs.getInt("headlines_font_size_sp_int", 13); - int headlineSmallFontSize = Math.max(10, Math.min(18, headlineFontSize - 2)); - - if (v == null) { - int layoutId = m_compactLayoutMode ? R.layout.headlines_row_compact : R.layout.headlines_row; - - switch (getItemViewType(position)) { - case VIEW_LOADMORE: - layoutId = R.layout.headlines_row_loadmore; - break; - case VIEW_UNREAD: - layoutId = m_compactLayoutMode ? R.layout.headlines_row_compact_unread : R.layout.headlines_row_unread; - break; - case VIEW_SELECTED: - layoutId = m_compactLayoutMode ? R.layout.headlines_row_compact_selected : R.layout.headlines_row; - break; - case VIEW_SELECTED_UNREAD: - layoutId = m_compactLayoutMode ? R.layout.headlines_row_compact_selected_unread : R.layout.headlines_row_unread; - break; - } - - LayoutInflater vi = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - v = vi.inflate(layoutId, null); - - holder = new ArticleViewHolder(v); - v.setTag(holder); - - // http://code.google.com/p/android/issues/detail?id=3414 - ((ViewGroup)v).setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); - } else { - holder = (ArticleViewHolder) v.getTag(); - } - - holder.articleId = articleId; - holder.flavorHeightStorage = m_flavorHeightStorage; - - // block footer clicks to make button/selection clicking easier - if (holder.headlineFooter != null) { - holder.headlineFooter.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - // - } - }); - } - - if (holder.textImage != null) { - final ArticleFlavorInfo afi = findFlavorImage(article); - - updateTextCheckedState(holder, article, afi); - - holder.textImage.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - Log.d(TAG, "textImage : onclicked"); - - SQLiteStatement stmtUpdate = m_activity.getDatabase().compileStatement("UPDATE articles SET selected = NOT selected " + - "WHERE " + BaseColumns._ID + " = ?"); - - stmtUpdate.bindLong(1, articleId); - stmtUpdate.execute(); - stmtUpdate.close(); - - updateTextCheckedState(holder, article, afi); - - refresh(); - - m_activity.invalidateOptionsMenu(); - } - }); - - ViewCompat.setTransitionName(holder.textImage, "gallery:" + afi.flavorImageUri); - - if (afi.flavorImageUri != null) { - - final String articleContent = article.getString(article.getColumnIndex("content")); - final String articleTitle = article.getString(article.getColumnIndex("title")); - - holder.textImage.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - openGalleryForType(afi, articleTitle, articleContent, holder, holder.textImage); - return true; - } - }); - - } - - - } - - if (holder.titleView != null) { - - holder.titleView.setText(Html.fromHtml(article.getString(article.getColumnIndex("title")))); - holder.titleView.setTextSize(TypedValue.COMPLEX_UNIT_SP, Math.min(21, headlineFontSize + 3)); - - int scoreIndex = article.getColumnIndex("score"); - if (scoreIndex >= 0) - adjustTitleTextView(article.getInt(scoreIndex), holder.titleView, position); - } - - int feedTitleIndex = article.getColumnIndex("feed_title"); - - if (holder.feedTitleView != null && feedTitleIndex != -1 && m_feedIsCat) { - String feedTitle = article.getString(feedTitleIndex); - - if (feedTitle.length() > 20) - feedTitle = feedTitle.substring(0, 20) + "..."; - - if (feedTitle.length() > 0) { - holder.feedTitleView.setTextSize(TypedValue.COMPLEX_UNIT_SP, headlineSmallFontSize); - holder.feedTitleView.setText(feedTitle); - } else { - holder.feedTitleView.setVisibility(View.GONE); - } - } else if (holder.feedTitleView != null) { - holder.feedTitleView.setVisibility(View.GONE); - } - - TypedValue tvTertiary = new TypedValue(); - m_activity.getTheme().resolveAttribute(R.attr.colorTertiary, tvTertiary, true); - - TypedValue tvPrimary = new TypedValue(); - m_activity.getTheme().resolveAttribute(R.attr.colorPrimary, tvPrimary, true); - - if (holder.attachmentsView != null) { - holder.attachmentsView.setVisibility(View.GONE); - } - - if (holder.scoreView != null) { - holder.scoreView.setVisibility(View.GONE); - } - - if (holder.markedView != null) { - TypedValue tv = new TypedValue(); - - boolean marked = article.getInt(article.getColumnIndex("marked")) == 1; - - m_activity.getTheme().resolveAttribute(marked ? R.attr.ic_star : R.attr.ic_star_outline, tv, true); - - holder.markedView.setIconResource(tv.resourceId); - - if (marked) - holder.markedView.setIconTint(ColorStateList.valueOf(tvTertiary.data)); - else - holder.markedView.setIconTint(ColorStateList.valueOf(tvPrimary.data)); - - holder.markedView.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - SQLiteStatement stmtUpdate = m_activity.getDatabase() - .compileStatement("UPDATE articles SET modified = 1, modified_marked = 1, marked = NOT marked " + - "WHERE " + BaseColumns._ID + " = ?"); - - stmtUpdate.bindLong(1, articleId); - stmtUpdate.execute(); - stmtUpdate.close(); - - refresh(); - } - }); - } - - if (holder.publishedView != null) { - TypedValue tv = new TypedValue(); - - boolean published = article.getInt(article.getColumnIndex("published")) == 1; - - m_activity.getTheme().resolveAttribute(published ? R.attr.ic_checkbox_marked : R.attr.ic_rss_box, tv, true); - - holder.publishedView.setIconResource(tv.resourceId); - - if (published) - holder.publishedView.setIconTint(ColorStateList.valueOf(tvTertiary.data)); - else - holder.publishedView.setIconTint(ColorStateList.valueOf(tvPrimary.data)); - - holder.publishedView.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - SQLiteStatement stmtUpdate = m_activity.getDatabase() - .compileStatement("UPDATE articles SET modified = 1, modified_published = 1, published = NOT published " + - "WHERE " + BaseColumns._ID + " = ?"); - - stmtUpdate.bindLong(1, articleId); - stmtUpdate.execute(); - stmtUpdate.close(); - - refresh(); - } - }); - } - - if (holder.excerptView != null) { - if (!m_prefs.getBoolean("headlines_show_content", true)) { - holder.excerptView.setVisibility(View.GONE); - } else { - String articleContent = article.getString(article.getColumnIndex("content")); - - String tmp = articleContent.length() > CommonActivity.EXCERPT_MAX_QUERY_LENGTH ? - articleContent.substring(0, CommonActivity.EXCERPT_MAX_QUERY_LENGTH) : articleContent; - - String excerpt = Jsoup.parse(tmp).text(); - - if (excerpt.length() > CommonActivity.EXCERPT_MAX_LENGTH) excerpt = excerpt.substring(0, CommonActivity.EXCERPT_MAX_LENGTH) + "…"; - - holder.excerptView.setTextSize(TypedValue.COMPLEX_UNIT_SP, headlineFontSize); - holder.excerptView.setText(excerpt); - } - } - - if (holder.authorView != null) { - int authorIndex = article.getColumnIndex("author"); - if (authorIndex >= 0) { - String author = article.getString(authorIndex); - - holder.authorView.setTextSize(TypedValue.COMPLEX_UNIT_SP, headlineSmallFontSize); - - if (author != null && author.length() > 0) - holder.authorView.setText(getString(R.string.author_formatted, author)); - else - holder.authorView.setText(""); - } - } - - if (holder.dateView != null) { - holder.dateView.setTextSize(TypedValue.COMPLEX_UNIT_SP, headlineSmallFontSize); - - Date d = new Date((long)article.getInt(article.getColumnIndex("updated")) * 1000); - DateFormat df = new SimpleDateFormat("MMM dd, HH:mm"); - df.setTimeZone(TimeZone.getDefault()); - holder.dateView.setText(df.format(d)); - } - - if (holder.selectionBoxView != null) { - holder.selectionBoxView.setChecked(article.getInt(article.getColumnIndex("selected")) == 1); - holder.selectionBoxView.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View view) { - CheckBox cb = (CheckBox) view; - - SQLiteStatement stmtUpdate = m_activity.getDatabase().compileStatement("UPDATE articles SET selected = ? " + - "WHERE " + BaseColumns._ID + " = ?"); - - stmtUpdate.bindLong(1, cb.isChecked() ? 1 : 0); - stmtUpdate.bindLong(2, articleId); - stmtUpdate.execute(); - stmtUpdate.close(); - - refresh(); - - m_activity.invalidateOptionsMenu(); - - } - }); - } - - if (holder.flavorImageHolder != null) { - - /* reset to default in case of convertview */ - holder.flavorImageLoadingBar.setVisibility(View.GONE); - holder.flavorImageView.setVisibility(View.GONE); - holder.flavorVideoKindView.setVisibility(View.GONE); - holder.flavorImageOverflow.setVisibility(View.GONE); - - // this is needed if our flavor image goes behind base listview element - holder.headlineHeader.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - m_listener.onArticleSelected(articleId); - } - }); - - holder.headlineHeader.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - m_activity.openContextMenu(v); - - return true; - } - }); - - if (showFlavorImage) { - final ArticleFlavorInfo afi = findFlavorImage(article); - - if (afi.flavorImageUri != null) { - holder.flavorImageView.setVisibility(View.VISIBLE); - - holder.flavorImageView.setMaxHeight((int)(m_screenHeight * 0.8f)); - - int flavorViewHeight = m_flavorHeightStorage.containsKey(articleId) ? m_flavorHeightStorage.get(articleId) : 0; - - //Log.d(TAG, articleId + " IMG: " + afi.flavorImageUri + " STREAM: " + afi.flavorStreamUri + " H:" + flavorViewHeight); - - if (flavorViewHeight > 0) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) holder.flavorImageView.getLayoutParams(); - lp.height = flavorViewHeight; - } - - final String articleContent = article.getString(article.getColumnIndex("content")); - final String articleTitle = article.getString(article.getColumnIndex("title")); - - - holder.flavorImageView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - - openGalleryForType(afi, articleTitle, articleContent, holder, holder.flavorImageView); - } - }); - - try { - - Glide.with(getContext()) - .load(afi.flavorImageUri) - //.dontTransform() - .diskCacheStrategy(DiskCacheStrategy.NONE) - .skipMemoryCache(false) - .listener(new RequestListener<String, GlideDrawable>() { - @Override - public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) { - - holder.flavorImageLoadingBar.setVisibility(View.GONE); - holder.flavorImageView.setVisibility(View.GONE); - - return false; - } - - @Override - public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) { - - holder.flavorImageLoadingBar.setVisibility(View.GONE); - - if (resource.getIntrinsicWidth() > HeadlinesFragment.FLAVOR_IMG_MIN_SIZE && - resource.getIntrinsicHeight() > HeadlinesFragment.FLAVOR_IMG_MIN_SIZE) { - - holder.flavorImageView.setVisibility(View.VISIBLE); - - adjustVideoKindView(holder, afi); - - return false; - } else { - - holder.flavorImageOverflow.setVisibility(View.GONE); - holder.flavorImageView.setVisibility(View.GONE); - - return true; - } - } - }) - .into(holder.flavorImageView); - } catch (OutOfMemoryError e) { - e.printStackTrace(); - } - - } - } - } - - if (holder.menuButtonView != null) { - //if (m_activity.isDarkTheme()) - // ib.setImageResource(R.drawable.ic_mailbox_collapsed_holo_dark); - - holder.menuButtonView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - - PopupMenu popup = new PopupMenu(getActivity(), v); - MenuInflater inflater = popup.getMenuInflater(); - inflater.inflate(R.menu.context_headlines, popup.getMenu()); - - popup.getMenu().findItem(R.id.article_set_labels).setVisible(false); - popup.getMenu().findItem(R.id.article_edit_note).setVisible(false); - - popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - return onArticleMenuItemSelected(item, articleId); - } - }); - - popup.show(); - } - }); - } - - return v; - } - - private void adjustVideoKindView(ArticleViewHolder holder, ArticleFlavorInfo afi) { - if (afi.flavorImageUri != null) { - if (afi.flavorStreamUri != null) { - holder.flavorVideoKindView.setImageResource(R.drawable.baseline_play_circle_24); - holder.flavorVideoKindView.setVisibility(View.VISIBLE); - } else if (afi.mediaList.size() > 1) { - holder.flavorVideoKindView.setImageResource(R.drawable.baseline_photo_album_24); - holder.flavorVideoKindView.setVisibility(View.VISIBLE); - } else { - holder.flavorVideoKindView.setVisibility(View.INVISIBLE); - } - } else { - holder.flavorVideoKindView.setVisibility(View.INVISIBLE); - } - } - - private void openGalleryForType(ArticleFlavorInfo afi, String title, String content, ArticleViewHolder viewHolder, View transitionView) { - - Intent intent = new Intent(m_activity, GalleryActivity.class); - - intent.putExtra("firstSrc", afi.flavorStreamUri != null ? afi.flavorStreamUri : afi.flavorImageUri); - intent.putExtra("title", title); - intent.putExtra("content", rewriteUrlsToLocal(content)); - - ActivityOptionsCompat options = - ActivityOptionsCompat.makeSceneTransitionAnimation(m_activity, - transitionView != null ? transitionView : viewHolder.flavorImageView, - "gallery:" + (afi.flavorStreamUri != null ? afi.flavorStreamUri : afi.flavorImageUri)); - - ActivityCompat.startActivity(m_activity, intent, options.toBundle()); - - } - - private String rewriteUrlsToLocal(String content) { - Document doc = Jsoup.parse(content); - - if (doc != null) { - List<Element> mediaList = doc.select("img,source"); - - for (Element e : mediaList) { - String url = e.attr("src"); - - if (url != null && ImageCacheService.isUrlCached(m_activity, url)) { - e.attr("src", "file://" + ImageCacheService.getCacheFileName(m_activity, url)); - } - } - - content = doc.html(); - } - - return content; - } - - private class ArticleFlavorInfo { - String flavorImageUri; - String flavorStreamUri; - public List<Element> mediaList = new ArrayList<>(); - } - - private ArticleFlavorInfo findFlavorImage(Cursor article) { - ArticleFlavorInfo afi = new ArticleFlavorInfo(); - - String content = article.getString(article.getColumnIndex("content")); - - if (content != null) { - Document articleDoc = Jsoup.parse(content); - - if (articleDoc != null) { - - Element flavorImage = null; - afi.mediaList = articleDoc.select("img,video"); - - for (Element e : afi.mediaList) { - flavorImage = e; - break; - } - - if (flavorImage != null) { - - try { - - if ("video".equals(flavorImage.tagName().toLowerCase())) { - Element source = flavorImage.select("source").first(); - - if (source != null) { - afi.flavorStreamUri = source.attr("src"); - afi.flavorImageUri = flavorImage.attr("poster"); - } - } else { - afi.flavorImageUri = flavorImage.attr("src"); - - if (afi.flavorImageUri.length() > 0 && afi.flavorImageUri.startsWith("//")) { - afi.flavorImageUri = "https:" + afi.flavorImageUri; - } - - afi.flavorStreamUri = null; - } - } catch (Exception e) { - e.printStackTrace(); - - afi.flavorImageUri = null; - afi.flavorStreamUri = null; - } - } - } - } - - if (afi.flavorImageUri != null && afi.flavorImageUri.length() > 0 && ImageCacheService.isUrlCached(m_activity, afi.flavorImageUri)) { - afi.flavorImageUri = "file://" + ImageCacheService.getCacheFileName(m_activity, afi.flavorImageUri); - } else { - afi.flavorImageUri = null; - } - - if (afi.flavorStreamUri != null && afi.flavorImageUri.length() > 0 && ImageCacheService.isUrlCached(m_activity, afi.flavorStreamUri)) { - afi.flavorStreamUri = "file://" + ImageCacheService.getCacheFileName(m_activity, afi.flavorStreamUri); - } else { - afi.flavorStreamUri = null; - } - - return afi; - } - - private void adjustTitleTextView(int score, TextView tv, int position) { - int viewType = getItemViewType(position); - if (origTitleColors[viewType] == null) - // store original color - origTitleColors[viewType] = Integer.valueOf(tv.getCurrentTextColor()); - - if (score < -500) { - tv.setPaintFlags(tv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); - } else { - tv.setTextColor(origTitleColors[viewType].intValue()); - tv.setPaintFlags(tv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG); - } - } - } - - public void notifyUpdated() { - m_adapter.notifyDataSetChanged(); - } - - public void setActiveArticleId(int articleId) { - m_activeArticleId = articleId; - try { - m_adapter.notifyDataSetChanged(); - - ListView list = getView().findViewById(R.id.headlines_list); - - Log.d(TAG, articleId + " position " + getArticleIdPosition(articleId)); - - if (list != null) { - list.setSelection(getArticleIdPosition(articleId)); - } - } catch (NullPointerException e) { - // invoked before view is created, nvm - } - } - - public Cursor getArticleAtPosition(int position) { - return (Cursor) m_list.getItemAtPosition(position); - } - - public int getArticleIdAtPosition(int position) { - Cursor c = getArticleAtPosition(position); - - if (c != null) { - int id = c.getInt(0); - return id; - } - - return 0; - - //return (int) m_adapter.getItemId(position + m_list.getHeaderViewsCount()); - } - - public int getActiveArticleId() { - return m_activeArticleId; - } - - public int getArticleIdPosition(int articleId) { - for (int i = 0; i < m_adapter.getCount(); i++) { - if (articleId == m_adapter.getItemId(i)) - return i + m_list.getHeaderViewsCount(); - } - - return -1; - } - - public int getArticleCount() { - return m_adapter.getCount(); - } - - public void setSearchQuery(String query) { - if (!m_searchQuery.equals(query)) { - m_searchQuery = query; - } - } - - public int getFeedId() { - return m_feedId; - } - - public boolean getFeedIsCat() { - return m_feedIsCat; - } - - public String getSearchQuery() { - return m_searchQuery; - } - - @Override - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - if (m_prefs.getBoolean("headlines_mark_read_scroll", false) && firstVisibleItem > (m_activity.isSmallScreen() ? 1 : 0)) { - //Article a = m_articles.get(firstVisibleItem - 1); - - Cursor article = getArticleAtPosition(firstVisibleItem - 1); - - if (article != null) { - Integer id = article.getInt(article.getColumnIndex(BaseColumns._ID)); - boolean unread = article.getInt(article.getColumnIndex("unread")) != 0; - - if (unread && !m_readArticleIds.contains(id)) { - m_readArticleIds.add(id); - } - } - } - } - - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - if (scrollState == SCROLL_STATE_IDLE && m_prefs.getBoolean("headlines_mark_read_scroll", false)) { - if (!m_readArticleIds.isEmpty()) { - - SQLiteStatement stmt = m_activity.getDatabase().compileStatement( - "UPDATE articles SET modified = 1, unread = 0 " + "WHERE " + BaseColumns._ID - + " = ?"); - - for (int articleId : m_readArticleIds) { - stmt.bindLong(1, articleId); - stmt.execute(); - } - - stmt.close(); - - m_autoMarkedArticleIds.addAll(m_readArticleIds); - m_readArticleIds.clear(); - - refresh(); - - } - } - } - -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineMasterActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineMasterActivity.java deleted file mode 100755 index ecff22ca..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineMasterActivity.java +++ /dev/null @@ -1,376 +0,0 @@ -package org.fox.ttrss.offline; - -import android.annotation.SuppressLint; -import android.app.Dialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.database.sqlite.SQLiteStatement; -import android.os.Bundle; -import android.os.Handler; -import android.preference.PreferenceManager; -import android.provider.BaseColumns; -import android.util.Log; -import android.view.Gravity; -import android.view.MenuItem; -import android.view.View; - -import org.fox.ttrss.Application; -import org.fox.ttrss.R; - -import androidx.appcompat.app.ActionBarDrawerToggle; -import androidx.appcompat.widget.Toolbar; -import androidx.drawerlayout.widget.DrawerLayout; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentTransaction; - -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - -import java.util.HashMap; - -public class OfflineMasterActivity extends OfflineActivity implements OfflineHeadlinesEventListener { - private final String TAG = this.getClass().getSimpleName(); - - private static final int OFFLINE_HEADLINES_REQUEST = 1; - - //private boolean m_actionbarUpEnabled = false; - //private int m_actionbarRevertDepth = 0; - private boolean m_feedIsSelected = false; - //private boolean m_feedWasSelected = false; - - private ActionBarDrawerToggle m_drawerToggle; - private DrawerLayout m_drawerLayout; - - @SuppressLint("NewApi") - @Override - public void onCreate(Bundle savedInstanceState) { - m_prefs = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()); - - setAppTheme(m_prefs); - - super.onCreate(savedInstanceState); - - if (m_prefs.getBoolean("force_phone_layout", false)) { - setContentView(R.layout.activity_master_phone); - } else { - setContentView(R.layout.activity_master); - } - - Toolbar toolbar = findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - setSmallScreen(findViewById(R.id.sw600dp_anchor) == null); - - Application.getInstance().load(savedInstanceState); - - m_drawerLayout = findViewById(R.id.headlines_drawer); - - if (m_drawerLayout != null) { - - m_drawerToggle = new ActionBarDrawerToggle(this, m_drawerLayout, R.string.blank, R.string.blank) { - @Override - public void onDrawerOpened(View drawerView) { - invalidateOptionsMenu(); - } - - @Override - public void onDrawerClosed(View drawerView) { - invalidateOptionsMenu(); - } - }; - - m_drawerLayout.addDrawerListener(m_drawerToggle); - m_drawerToggle.setDrawerIndicatorEnabled(true); - } - - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setHomeButtonEnabled(true); - - if (savedInstanceState != null) { - - //m_actionbarUpEnabled = savedInstanceState.getBoolean("actionbarUpEnabled"); - //m_actionbarRevertDepth = savedInstanceState.getInt("actionbarRevertDepth"); - m_feedIsSelected = savedInstanceState.getBoolean("feedIsSelected"); - //m_feedWasSelected = savedInstanceState.getBoolean("feedWasSelected"); - - /* if (findViewById(R.id.sw600dp_port_anchor) != null && m_feedWasSelected && m_slidingMenu != null) { - m_slidingMenu.setBehindWidth(getScreenWidthInPixel() * 2/3); - } */ - - if (m_drawerLayout != null && m_feedIsSelected == false) { - m_drawerLayout.openDrawer(Gravity.START); - } - - } else { - if (m_drawerLayout != null) { - m_drawerLayout.openDrawer(Gravity.START); - } - - FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); - - if (m_prefs.getBoolean("enable_cats", false)) { - ft.replace(R.id.feeds_fragment, new OfflineFeedCategoriesFragment(), FRAG_CATS); - } else { - ft.replace(R.id.feeds_fragment, new OfflineFeedsFragment(), FRAG_FEEDS); - } - - ft.commit(); - } - } - - protected void onPostCreate(Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); - // Sync the toggle state after onRestoreInstanceState has occurred. - if (m_drawerToggle != null) m_drawerToggle.syncState(); - } - - /*public void openFeedArticles(int feedId, boolean isCat) { - if (isSmallScreen()) { - Intent intent = new Intent(OfflineMasterActivity.this, OfflineDetailActivity.class); - - intent.putExtra("feed", feedId); - intent.putExtra("isCat", isCat); - intent.putExtra("article", 0); - startActivityForResult(intent, 0); - } - }*/ - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (m_drawerToggle != null && m_drawerToggle.onOptionsItemSelected(item)) { - return true; - } - - if (item.getItemId() == R.id.headlines_toggle_sort_order) {/* SharedPreferences.Editor editor = m_prefs.edit(); - editor.putBoolean("offline_oldest_first", !m_prefs.getBoolean("offline_oldest_first", false)); - editor.commit(); - refresh(); */ - - Dialog dialog = new Dialog(this); - - int selectedIndex = m_prefs.getBoolean("offline_oldest_first", false) ? 1 : 0; - - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this) - .setTitle(getString(R.string.headlines_sort_articles_title)) - .setSingleChoiceItems( - new String[]{ - getString(R.string.headlines_sort_default), - getString(R.string.headlines_sort_oldest_first) - }, - selectedIndex, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, - int which) { - switch (which) { - case 0: - if (true) { - SharedPreferences.Editor editor = m_prefs.edit(); - editor.putBoolean("offline_oldest_first", false); - editor.apply(); - } - break; - case 1: - if (true) { - SharedPreferences.Editor editor = m_prefs.edit(); - editor.putBoolean("offline_oldest_first", true); - editor.apply(); - } - break; - } - dialog.cancel(); - - refresh(); - } - }); - - dialog = builder.create(); - dialog.show(); - - return true; - /* case R.id.show_feeds: - setUnreadOnly(!getUnreadOnly()); - invalidateOptionsMenu(); - refresh(); - return true; */ - } - Log.d(TAG, "onOptionsItemSelected, unhandled id=" + item.getItemId()); - return super.onOptionsItemSelected(item); - } - - @Override - public void onSaveInstanceState(Bundle out) { - super.onSaveInstanceState(out); - - out.putBoolean("feedIsSelected", m_feedIsSelected); - - Application.getInstance().save(out); - } - - public void initMenu() { - super.initMenu(); - - if (m_menu != null) { - Fragment ff = getSupportFragmentManager().findFragmentByTag(FRAG_FEEDS); - Fragment cf = getSupportFragmentManager().findFragmentByTag(FRAG_CATS); - OfflineHeadlinesFragment hf = (OfflineHeadlinesFragment)getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES); - - /* if (m_drawerLayout != null) { - boolean isDrawerOpen = m_drawerLayout.isDrawerOpen(Gravity.START); - - m_menu.setGroupVisible(R.id.menu_group_feeds, isDrawerOpen); - m_menu.setGroupVisible(R.id.menu_group_headlines, hf != null && hf.isAdded() && !isDrawerOpen); - } else { - m_menu.setGroupVisible(R.id.menu_group_feeds, (ff != null && ff.isAdded()) || (cf != null && cf.isAdded())); - m_menu.setGroupVisible(R.id.menu_group_headlines, hf != null && hf.isAdded()); - } */ - - m_menu.setGroupVisible(R.id.menu_group_feeds, (ff != null && ff.isAdded()) || (cf != null && cf.isAdded())); - m_menu.setGroupVisible(R.id.menu_group_headlines, hf != null && hf.isAdded()); - - //m_menu.findItem(R.id.headlines_toggle_sidebar).setVisible(false); - - /* MenuItem item = m_menu.findItem(R.id.show_feeds); - - if (getUnreadOnly()) { - item.setTitle(R.string.menu_all_feeds); - } else { - item.setTitle(R.string.menu_unread_feeds); - } */ - } - } - - public void onCatSelected(int catId) { - onCatSelected(catId, m_prefs.getBoolean("browse_cats_like_feeds", false)); - } - - public void onCatSelected(int catId, boolean openAsFeed) { - OfflineFeedCategoriesFragment fc = (OfflineFeedCategoriesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_CATS); - - if (openAsFeed) { - if (fc != null) { - fc.setSelectedFeedId(catId); - } - - onFeedSelected(catId, true, true); - } else { - if (fc != null) { - fc.setSelectedFeedId(-1); - } - - FragmentTransaction ft = getSupportFragmentManager() - .beginTransaction(); - - OfflineFeedsFragment ff = new OfflineFeedsFragment(); - ff.initialize(catId, true); - - ft.replace(R.id.feeds_fragment, ff, FRAG_FEEDS); - ft.addToBackStack(null); - - //getSupportActionBar().setDisplayHomeAsUpEnabled(true); - //m_actionbarUpEnabled = true; - //m_actionbarRevertDepth = m_actionbarRevertDepth + 1; - - ft.commit(); - } - } - - @Override - public void onBackPressed() { - if (m_drawerLayout != null && !m_drawerLayout.isDrawerOpen(Gravity.START) && - (getSupportFragmentManager().getBackStackEntryCount() > 0 || m_feedIsSelected)) { - - m_drawerLayout.openDrawer(Gravity.START); - } else { - try { - super.onBackPressed(); - } catch (IllegalStateException e) { - // java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState - e.printStackTrace(); - } - } - } - - public void onFeedSelected(int feedId) { - onFeedSelected(feedId, false, true); - } - - public void onFeedSelected(final int feedId, final boolean isCat, boolean open) { - - if (open) { - - if (m_drawerLayout != null) { - m_drawerLayout.closeDrawers(); - } - - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - FragmentTransaction ft = getSupportFragmentManager() - .beginTransaction(); - - OfflineHeadlinesFragment hf = new OfflineHeadlinesFragment(); - hf.initialize(feedId, isCat, false); - ft.replace(R.id.headlines_fragment, hf, FRAG_HEADLINES); - - ft.commit(); - - m_feedIsSelected = true; - //m_feedWasSelected = true; - - } - }, 250); - } - } - - @Override - public void onArticleSelected(int articleId, boolean open) { - - if (!open) { - SQLiteStatement stmt = getDatabase().compileStatement( - "UPDATE articles SET modified = 1, unread = 0 " + "WHERE " + BaseColumns._ID - + " = ?"); - - stmt.bindLong(1, articleId); - stmt.execute(); - stmt.close(); - } - - invalidateOptionsMenu(); - - if (open) { - OfflineHeadlinesFragment hf = (OfflineHeadlinesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES); - - Intent intent = new Intent(OfflineMasterActivity.this, OfflineDetailActivity.class); - intent.putExtra("feed", hf.getFeedId()); - intent.putExtra("isCat", hf.getFeedIsCat()); - intent.putExtra("article", articleId); - - startActivityForResult(intent, OFFLINE_HEADLINES_REQUEST); - overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left); - - } else { - refresh(); - } - - } - - @Override - public void onArticleSelected(int articleId) { - onArticleSelected(articleId, true); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == OFFLINE_HEADLINES_REQUEST) { - - OfflineHeadlinesFragment ohf = (OfflineHeadlinesFragment)getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES); - - if (ohf != null) { - ohf.refresh(); - } - } - - } - -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineUploadService.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineUploadService.java deleted file mode 100755 index efbeef2c..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineUploadService.java +++ /dev/null @@ -1,282 +0,0 @@ -package org.fox.ttrss.offline; - -import android.app.IntentService; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.graphics.BitmapFactory; -import android.os.Build; -import android.util.Log; - -import com.google.gson.JsonElement; - -import org.fox.ttrss.ApiRequest; -import org.fox.ttrss.CommonActivity; -import org.fox.ttrss.OnlineActivity; -import org.fox.ttrss.R; -import org.fox.ttrss.util.DatabaseHelper; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import androidx.core.app.NotificationCompat; - -public class OfflineUploadService extends IntentService { - private final String TAG = this.getClass().getSimpleName(); - - public static final int NOTIFY_UPLOADING = 2; - public static final String INTENT_ACTION_SUCCESS = "org.fox.ttrss.intent.action.UploadComplete"; - - private String m_sessionId; - private NotificationManager m_nmgr; - private boolean m_uploadInProgress = false; - private boolean m_batchMode = false; - private DatabaseHelper m_databaseHelper; - - public OfflineUploadService() { - super("OfflineUploadService"); - } - - @Override - public void onCreate() { - super.onCreate(); - m_nmgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - - initDatabase(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - - m_nmgr.cancel(NOTIFY_UPLOADING); - } - - @SuppressWarnings("deprecation") - private void updateNotification(String msg, int progress, int max, boolean showProgress, boolean isError) { - PendingIntent contentIntent = PendingIntent.getActivity(this, 0, - new Intent(this, OnlineActivity.class), PendingIntent.FLAG_IMMUTABLE); - - NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext()) - .setContentText(msg) - .setContentTitle(getString(R.string.notify_uploading_title)) - .setContentIntent(contentIntent) - .setWhen(System.currentTimeMillis()) - .setSmallIcon(R.drawable.baseline_cloud_upload_24) - .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), - R.drawable.ic_launcher)) - .setOngoing(!isError) - .setOnlyAlertOnce(true) - .setVibrate(new long[0]); - - if (showProgress) builder.setProgress(max, progress, max == 0); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - builder.setCategory(Notification.CATEGORY_PROGRESS) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - .setColor(0x88b0f0) - .setGroup("org.fox.ttrss") - .addAction(R.drawable.ic_launcher, getString(R.string.offline_sync_try_again), contentIntent); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - builder.setChannelId(CommonActivity.NOTIFICATION_CHANNEL_NORMAL); - } - - m_nmgr.notify(NOTIFY_UPLOADING, builder.build()); - } - - private void updateNotification(int msgResId, int progress, int max, boolean showProgress, boolean isError) { - updateNotification(getString(msgResId), progress, max, showProgress, isError); - } - - private void initDatabase() { - m_databaseHelper = DatabaseHelper.getInstance(this); - } - - private synchronized SQLiteDatabase getDatabase() { - return m_databaseHelper.getWritableDatabase(); - } - - private enum ModifiedCriteria { - READ, MARKED, UNMARKED, PUBLISHED, UNPUBLISHED - } - - private List<Integer> getModifiedIds(ModifiedCriteria criteria) { - - String criteriaStr = ""; - - switch (criteria) { - case READ: - criteriaStr = "unread = 0"; - break; - case MARKED: - criteriaStr = "modified_marked = 1 AND marked = 1"; - break; - case UNMARKED: - criteriaStr = "modified_marked = 1 AND marked = 0"; - break; - case PUBLISHED: - criteriaStr = "modified_published = 1 AND published = 1"; - break; - case UNPUBLISHED: - criteriaStr = "modified_published = 1 AND published = 0"; - break; - } - - Cursor c = getDatabase().query("articles", null, - "modified = 1 AND " + criteriaStr, null, null, null, null); - - List<Integer> tmp = new ArrayList<>(); - - while (c.moveToNext()) { - tmp.add(c.getInt(0)); - } - - c.close(); - - return tmp; - } - - private void uploadFailed() { - m_uploadInProgress = false; - } - - private void uploadSuccess() { - getDatabase().execSQL("UPDATE articles SET modified = 0"); - - if (m_batchMode) { - - SharedPreferences localPrefs = getSharedPreferences("localprefs", Context.MODE_PRIVATE); - SharedPreferences.Editor editor = localPrefs.edit(); - editor.putBoolean("offline_mode_active", false); - editor.apply(); - - } else { - Intent intent = new Intent(); - intent.setAction(INTENT_ACTION_SUCCESS); - intent.addCategory(Intent.CATEGORY_DEFAULT); - sendBroadcast(intent); - } - - m_uploadInProgress = false; - - m_nmgr.cancel(NOTIFY_UPLOADING); - } - - interface CriteriaCallback { - void onUploadSuccess(); - } - - private void uploadByCriteria(final ModifiedCriteria criteria, final CriteriaCallback callback) { - - final List<Integer> ids = getModifiedIds(criteria); - - Log.d(TAG, "syncing modified offline data for " + criteria + ": " + ids); - - if (ids.size() > 0) { - ApiRequest req = new ApiRequest(getApplicationContext()) { - @Override - protected void onPostExecute(JsonElement result) { - if (result != null) { - callback.onUploadSuccess(); - } else { - Log.d(TAG, "syncing failed: " + getErrorMessage()); - - updateNotification(getErrorMessage(), 0, 0, false, true); - uploadFailed(); - } - } - }; - - @SuppressWarnings("serial") - HashMap<String, String> map = new HashMap<String, String>(); - map.put("sid", m_sessionId); - map.put("op", "updateArticle"); - map.put("article_ids", android.text.TextUtils.join(",", ids)); - - switch (criteria) { - case READ: - map.put("mode", "0"); - map.put("field", "2"); - break; - case PUBLISHED: - map.put("mode", "1"); - map.put("field", "1"); - break; - case UNPUBLISHED: - map.put("mode", "0"); - map.put("field", "1"); - break; - case MARKED: - map.put("mode", "1"); - map.put("field", "0"); - break; - case UNMARKED: - map.put("mode", "0"); - map.put("field", "0"); - break; - } - - req.execute(map); - } else { - callback.onUploadSuccess(); - } - } - - @Override - protected void onHandleIntent(Intent intent) { - try { - if (getDatabase().isDbLockedByCurrentThread() || getDatabase().isDbLockedByOtherThreads()) { - return; - } - - m_sessionId = intent.getStringExtra("sessionId"); - m_batchMode = intent.getBooleanExtra("batchMode", false); - - if (!m_uploadInProgress) { - m_uploadInProgress = true; - - updateNotification(R.string.notify_uploading_sending_data, 0, 0, true, true); - - uploadByCriteria(ModifiedCriteria.READ, new CriteriaCallback() { - @Override - public void onUploadSuccess() { - uploadByCriteria(ModifiedCriteria.MARKED, new CriteriaCallback() { - @Override - public void onUploadSuccess() { - uploadByCriteria(ModifiedCriteria.UNMARKED, new CriteriaCallback() { - @Override - public void onUploadSuccess() { - uploadByCriteria(ModifiedCriteria.PUBLISHED, new CriteriaCallback() { - @Override - public void onUploadSuccess() { - uploadByCriteria(ModifiedCriteria.UNPUBLISHED, new CriteriaCallback() { - @Override - public void onUploadSuccess() { - Log.d(TAG, "upload complete"); - - uploadSuccess(); - } - }); - } - }); - } - }); - } - }); - } - }); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/util/ImageCacheService.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/util/ImageCacheService.java deleted file mode 100755 index b2ae08f7..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/util/ImageCacheService.java +++ /dev/null @@ -1,323 +0,0 @@ -package org.fox.ttrss.util; - -import android.app.ActivityManager; -import android.app.ActivityManager.RunningServiceInfo; -import android.app.IntentService; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.graphics.BitmapFactory; -import android.os.Build; -import android.os.Environment; -import android.util.Log; - -import org.fox.ttrss.CommonActivity; -import org.fox.ttrss.OnlineActivity; -import org.fox.ttrss.R; -import org.fox.ttrss.offline.OfflineDownloadService; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Date; - -import androidx.core.app.NotificationCompat; - -public class ImageCacheService extends IntentService { - - @SuppressWarnings("unused") - private final String TAG = this.getClass().getSimpleName(); - - public static final int NOTIFY_DOWNLOADING = 1; - public static final int NOTIFY_DOWNLOAD_SUCCESS = 2; - - public static final String INTENT_ACTION_ICS_STOP = "org.fox.ttrss.intent.action.ICSStop"; - - private static final String CACHE_PATH = "/image-cache/"; - - private int m_imagesDownloaded = 0; - private boolean m_canProceed = true; - - private NotificationManager m_nmgr; - private BroadcastReceiver m_receiver; - private int m_queueSize = 0; - - public ImageCacheService() { - super("ImageCacheService"); - } - - private boolean isDownloadServiceRunning() { - ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); - for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { - if ("org.fox.ttrss.OfflineDownloadService".equals(service.service.getClassName())) { - return true; - } - } - return false; - } - - - @Override - public void onCreate() { - super.onCreate(); - m_nmgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - - m_receiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Log.d(TAG, "received broadcast action: " + intent.getAction()); - - if (INTENT_ACTION_ICS_STOP.equals(intent.getAction())) { - m_canProceed = false; - } - } - }; - - IntentFilter filter = new IntentFilter(); - filter.addAction(INTENT_ACTION_ICS_STOP); - filter.addCategory(Intent.CATEGORY_DEFAULT); - - registerReceiver(m_receiver, filter); - } - - public static boolean isUrlCached(Context context, String url) { - String hashedUrl = md5(url); - - File storage = context.getExternalCacheDir(); - - File file = new File(storage.getAbsolutePath() + CACHE_PATH + "/" + hashedUrl); - - return file.exists(); - } - - public static String getCacheFileName(Context context, String url) { - String hashedUrl = md5(url); - - File storage = context.getExternalCacheDir(); - - File file = new File(storage.getAbsolutePath() + CACHE_PATH + "/" + hashedUrl); - - return file.getAbsolutePath(); - } - - public static void cleanupCache(Context context, boolean deleteAll) { - if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { - File storage = context.getExternalCacheDir(); - File cachePath = new File(storage.getAbsolutePath() + CACHE_PATH); - - long now = new Date().getTime(); - - if (cachePath.isDirectory()) { - for (File file : cachePath.listFiles()) { - if (deleteAll || now - file.lastModified() > 1000*60*60*24*7) { - file.delete(); - } - } - } - } - } - - protected static String md5(String s) { - try { - MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); - digest.update(s.getBytes()); - byte messageDigest[] = digest.digest(); - - StringBuilder hexString = new StringBuilder(); - for (int i=0; i<messageDigest.length; i++) - hexString.append(Integer.toHexString(0xFF & messageDigest[i])); - - return hexString.toString(); - - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - - return null; - } - - private InputStream getStream(String urlString) { - try { - URL url = new URL(urlString); - URLConnection urlConnection = url.openConnection(); - urlConnection.setConnectTimeout(250); - urlConnection.setReadTimeout(5*1000); - return urlConnection.getInputStream(); - } catch (Exception ex) { - return null; - } - } - - @SuppressWarnings("deprecation") - private void notifyDownloadSuccess() { - Intent intent = new Intent(this, OnlineActivity.class); - intent.setAction(OfflineDownloadService.INTENT_ACTION_SWITCH_OFFLINE); - - PendingIntent contentIntent = PendingIntent.getActivity(this, OfflineDownloadService.PI_SUCCESS, - intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - - NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext()) - .setContentTitle(getString(R.string.dialog_offline_success)) - .setContentText(getString(R.string.offline_tap_to_switch)) - .setContentIntent(contentIntent) - .setWhen(System.currentTimeMillis()) - .setSmallIcon(R.drawable.ic_notification) - .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), - R.drawable.ic_launcher)) - .setOnlyAlertOnce(true) - .setPriority(Notification.PRIORITY_HIGH) - .setDefaults(Notification.DEFAULT_ALL) - .setAutoCancel(true); - - builder.setCategory(Notification.CATEGORY_MESSAGE) - .setVibrate(new long[0]) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - .setColor(0x88b0f0) - .setGroup("org.fox.ttrss"); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - builder.setChannelId(CommonActivity.NOTIFICATION_CHANNEL_PRIORITY); - } - - m_nmgr.notify(NOTIFY_DOWNLOAD_SUCCESS, builder.build()); - } - - - @SuppressWarnings("deprecation") - private void updateNotification(String msg, int progress, int max, boolean showProgress) { - Intent intent = new Intent(this, OnlineActivity.class); - - PendingIntent contentIntent = PendingIntent.getActivity(this, OfflineDownloadService.PI_GENERIC, - intent, PendingIntent.FLAG_IMMUTABLE); - - NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext()) - .setContentText(msg) - .setContentTitle(getString(R.string.notify_downloading_title)) - .setContentIntent(contentIntent) - .setWhen(System.currentTimeMillis()) - .setSmallIcon(R.drawable.baseline_cloud_download_24) - .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), - R.drawable.ic_launcher)) - .setOngoing(true) - .setOnlyAlertOnce(true); - - if (showProgress) builder.setProgress(max, progress, max == 0); - - intent = new Intent(this, OnlineActivity.class); - intent.setAction(OfflineDownloadService.INTENT_ACTION_CANCEL); - - PendingIntent cancelIntent = PendingIntent.getActivity(this, - OfflineDownloadService.PI_CANCEL, intent, PendingIntent.FLAG_IMMUTABLE); - - builder.setCategory(Notification.CATEGORY_PROGRESS) - .setVibrate(new long[0]) - .setVisibility(NotificationCompat.VISIBILITY_PRIVATE) - .setColor(0x88b0f0) - .setGroup("org.fox.ttrss") - .addAction(R.drawable.ic_launcher, getString(R.string.cancel), cancelIntent); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - builder.setChannelId(CommonActivity.NOTIFICATION_CHANNEL_NORMAL); - } - - m_nmgr.notify(NOTIFY_DOWNLOADING, builder.build()); - } - - /* private void updateNotification(int msgResId) { - updateNotification(getString(msgResId)); - } */ - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - - m_queueSize++; - - return super.onStartCommand(intent, flags, startId); - } - - @Override - protected void onHandleIntent(Intent intent) { - - m_queueSize--; - m_imagesDownloaded++; - - String url = intent.getStringExtra("url"); - - Log.d(TAG, "got request to download URL=" + url + "; canProceed=" + m_canProceed); - - if (!m_canProceed || !Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) - return; - - String hashedUrl = md5(url); - - File storage = getExternalCacheDir(); - File cachePath = new File(storage.getAbsolutePath() + CACHE_PATH); - if (!cachePath.exists()) cachePath.mkdirs(); - - if (cachePath.isDirectory() && hashedUrl != null) { - File outputFile = new File(cachePath.getAbsolutePath() + "/" + hashedUrl); - - if (!outputFile.exists()) { - - //Log.d(TAG, "downloading to " + outputFile.getAbsolutePath()); - - InputStream is = getStream(url); - - if (is != null) { - try { - FileOutputStream fos = new FileOutputStream(outputFile); - - byte[] buffer = new byte[1024]; - int len = 0; - while ((len = is.read(buffer)) != -1) { - fos.write(buffer, 0, len); - } - - fos.close(); - is.close(); - - updateNotification(getString(R.string.notify_downloading_media), m_imagesDownloaded, - m_imagesDownloaded+m_queueSize, true); - - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - - if (!isDownloadServiceRunning()) { - m_nmgr.cancel(NOTIFY_DOWNLOADING); - - /*Intent success = new Intent(); - success.setAction(OfflineDownloadService.INTENT_ACTION_SUCCESS); - success.addCategory(Intent.CATEGORY_DEFAULT); - sendBroadcast(success);*/ - - try { - unregisterReceiver(m_receiver); - } catch (Exception e) { - e.printStackTrace(); - } - - if (m_canProceed) { - notifyDownloadSuccess(); - } - } - } - -} diff --git a/org.fox.ttrss/src/main/res/xml/preferences.xml b/org.fox.ttrss/src/main/res/xml/preferences.xml index 3c422e7e..81fbd5f1 100755 --- a/org.fox.ttrss/src/main/res/xml/preferences.xml +++ b/org.fox.ttrss/src/main/res/xml/preferences.xml @@ -181,26 +181,6 @@ android:summary="@string/prefs_always_open_uri_summary" android:title="@string/prefs_always_open_uri" /> </PreferenceCategory> - <PreferenceCategory android:title="@string/offline_mode" > - <ListPreference - android:defaultValue="250" - android:entries="@array/pref_offline_amounts" - android:entryValues="@array/pref_offline_amounts" - android:key="offline_sync_max" - android:summary="@string/offline_articles_to_download_long" - android:title="@string/offline_articles_to_download" /> - - <SwitchPreferenceCompat - android:defaultValue="false" - android:key="offline_sort_by_feed" - android:title="@string/prefs_offline_sort_by_feed" /> - - <SwitchPreferenceCompat - android:defaultValue="false" - android:key="offline_image_cache_enabled" - android:summary="@string/offline_media_cache_enabled_summary" - android:title="@string/offline_media_cache_enabled" /> - </PreferenceCategory> <PreferenceCategory android:title="@string/prefs_widget" > <ListPreference android:defaultValue="15" |