summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xorg.fox.ttrss/build.gradle16
-rwxr-xr-xorg.fox.ttrss/src/main/AndroidManifest.xml23
-rw-r--r--org.fox.ttrss/src/main/java/org/fox/ttrss/ApiCommon.java3
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/ApiLoader.java4
-rw-r--r--org.fox.ttrss/src/main/java/org/fox/ttrss/ApiRequest.java4
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/ArticleFragment.java113
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/ArticlePager.java76
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/BaseFeedlistFragment.java160
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/CommonActivity.java1
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/DetailActivity.java110
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/GalleryActivity.java7
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java24
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/LogcatActivity.java2
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/OnlineActivity.java269
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/PreferencesFragment.java1
-rw-r--r--org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OkHttpProgressGlideModule.java28
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/glide/WrappingTarget.java4
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineActivity.java845
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineArticleFragment.java505
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineArticlePager.java288
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineDetailActivity.java267
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineDownloadService.java594
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineFeedCategoriesFragment.java358
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineFeedsFragment.java367
-rw-r--r--org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesEventListener.java7
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesFragment.java1311
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineMasterActivity.java376
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineUploadService.java282
-rw-r--r--org.fox.ttrss/src/main/java/org/fox/ttrss/util/DetailActivityScrollingViewBehavior.java15
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/util/HeaderViewRecyclerAdapter.java4
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/util/ImageCacheService.java323
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/widget/WidgetUpdateService.java6
-rw-r--r--org.fox.ttrss/src/main/res/drawable/baseline_mark_as_unread_24.xml5
-rw-r--r--org.fox.ttrss/src/main/res/drawable/baseline_mark_email_unread_24.xml5
-rw-r--r--org.fox.ttrss/src/main/res/drawable/baseline_new_label_24.xml5
-rw-r--r--org.fox.ttrss/src/main/res/drawable/baseline_note_add_24.xml5
-rw-r--r--org.fox.ttrss/src/main/res/layout-sw600dp-land/activity_detail.xml16
-rwxr-xr-xorg.fox.ttrss/src/main/res/layout/fragment_article.xml232
-rwxr-xr-xorg.fox.ttrss/src/main/res/layout/fragment_article_pager.xml2
-rwxr-xr-xorg.fox.ttrss/src/main/res/layout/fragment_headlines_offline.xml23
-rwxr-xr-xorg.fox.ttrss/src/main/res/layout/headlines_row_compact.xml89
-rwxr-xr-xorg.fox.ttrss/src/main/res/layout/headlines_row_compact_selected.xml86
-rwxr-xr-xorg.fox.ttrss/src/main/res/layout/headlines_row_compact_selected_unread.xml93
-rwxr-xr-xorg.fox.ttrss/src/main/res/layout/headlines_row_compact_unread.xml76
-rw-r--r--org.fox.ttrss/src/main/res/layout/layout_detail_phone.xml30
-rw-r--r--org.fox.ttrss/src/main/res/menu/action_mode_headlines.xml2
-rwxr-xr-xorg.fox.ttrss/src/main/res/menu/activity_main.xml28
-rw-r--r--org.fox.ttrss/src/main/res/menu/bottombar_detail.xml38
-rw-r--r--org.fox.ttrss/src/main/res/menu/context_headlines.xml6
-rwxr-xr-xorg.fox.ttrss/src/main/res/values/strings.xml2
-rwxr-xr-xorg.fox.ttrss/src/main/res/xml/preferences.xml20
51 files changed, 623 insertions, 6533 deletions
diff --git a/org.fox.ttrss/build.gradle b/org.fox.ttrss/build.gradle
index be621d57..c8d9b3d5 100755
--- a/org.fox.ttrss/build.gradle
+++ b/org.fox.ttrss/build.gradle
@@ -13,7 +13,7 @@ android {
//noinspection ExpiredTargetSdkVersion
targetSdkVersion 31
compileSdk 35
- versionCode 563
+ versionCode getGitVersionCode()
versionName getVersion()
vectorDrawables.useSupportLibrary = true
}
@@ -55,10 +55,18 @@ android {
}
}
+def getGitVersionCode() {
+ return new Date(getGitTimestamp()).format('yyyyMMdd').toInteger()
+}
+
+def getGitTimestampFormatted() {
+ return new Date(getGitTimestamp()).format('YY.MM')
+}
+
def getGitTimestamp() {
// gitlab CI iso-8601 timestamp
if (System.getenv("CI_COMMIT_TIMESTAMP")) {
- return Date.parse("yyyy-MM-dd'T'HH:mm:ssXXX", System.getenv("CI_COMMIT_TIMESTAMP")).format('YY.MM')
+ return Date.parse("yyyy-MM-dd'T'HH:mm:ssXXX", System.getenv("CI_COMMIT_TIMESTAMP")).getTime();
}
// try to get version from git repo in current dir
@@ -69,7 +77,7 @@ def getGitTimestamp() {
standardOutput = stdout
}
- return new Date(stdout.toString().trim().toLong() * 1000).format('YY.MM')
+ return stdout.toString().trim().toLong() * 1000;
}
catch (ignored) {
return 0;
@@ -97,7 +105,7 @@ def getGitCommitHash() {
}
def getVersion() {
- return getGitTimestamp() + '-' + getGitCommitHash();
+ return getGitTimestampFormatted() + '-' + getGitCommitHash();
}
dependencies {
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/ApiCommon.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiCommon.java
index ce5089f8..9fd0623a 100644
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiCommon.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiCommon.java
@@ -9,6 +9,8 @@ import android.net.NetworkInfo;
import android.preference.PreferenceManager;
import android.util.Log;
+import androidx.annotation.NonNull;
+
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -18,7 +20,6 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
-import androidx.annotation.NonNull;
import okhttp3.Credentials;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiLoader.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiLoader.java
index 95f7fa87..18eedee1 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiLoader.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiLoader.java
@@ -2,14 +2,14 @@ package org.fox.ttrss;
import android.content.Context;
+import androidx.loader.content.AsyncTaskLoader;
+
import com.google.gson.JsonElement;
import org.fox.ttrss.ApiCommon.ApiError;
import java.util.HashMap;
-import androidx.loader.content.AsyncTaskLoader;
-
public class ApiLoader extends AsyncTaskLoader<JsonElement> implements ApiCommon.ApiCaller {
private final String TAG = this.getClass().getSimpleName();
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiRequest.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiRequest.java
index e993a866..e6c323e9 100644
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiRequest.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiRequest.java
@@ -1,5 +1,7 @@
package org.fox.ttrss;
+import static org.fox.ttrss.ApiCommon.ApiError;
+
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
@@ -8,8 +10,6 @@ import com.google.gson.JsonElement;
import java.util.HashMap;
-import static org.fox.ttrss.ApiCommon.ApiError;
-
public class ApiRequest extends AsyncTask<HashMap<String,String>, Integer, JsonElement> implements ApiCommon.ApiCaller {
private final String TAG = this.getClass().getSimpleName();
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleFragment.java
index dd27631b..2b2bf090 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleFragment.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleFragment.java
@@ -16,19 +16,15 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.webkit.WebBackForwardList;
-import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebView.HitTestResult;
import android.webkit.WebViewClient;
-import android.widget.EditText;
-import android.widget.FrameLayout;
import android.widget.TextView;
import androidx.core.text.HtmlCompat;
import com.google.android.material.button.MaterialButton;
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.fox.ttrss.types.Article;
import org.fox.ttrss.types.Attachment;
@@ -39,6 +35,7 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
+// TODO: add ability to update already rendered contents from article somehow (to refresh note, etc)
public class ArticleFragment extends androidx.fragment.app.Fragment {
private final String TAG = this.getClass().getSimpleName();
@@ -46,10 +43,6 @@ public class ArticleFragment extends androidx.fragment.app.Fragment {
protected Article m_article;
private DetailActivity m_activity;
private WebView m_web;
- protected View m_customView;
- protected FrameLayout m_customViewContainer;
- protected View m_contentView;
- protected FSVideoChromeClient m_chromeClient;
//protected View m_fab;
protected int m_articleFontSize;
protected int m_articleSmallFontSize;
@@ -58,68 +51,6 @@ public class ArticleFragment extends androidx.fragment.app.Fragment {
m_article = article;
}
- 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);
- }
- }
-
- //private View.OnTouchListener m_gestureListener;
-
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
@@ -169,13 +100,6 @@ public class ArticleFragment extends androidx.fragment.app.Fragment {
m_activity.finish();
}
- /* if (m_fsviewShown) {
- view.findViewById(R.id.article_fullscreen_video).setVisibility(View.VISIBLE);
- view.findViewById(R.id.article_scrollview).setVisibility(View.INVISIBLE);
- } */
-
- m_customViewContainer = view.findViewById(R.id.article_fullscreen_video);
-
/* if (m_article.id == HeadlinesFragment.ARTICLE_SPECIAL_TOP_CHANGED) {
TextView statusMessage = (TextView) view.findViewById(R.id.article_status_message);
statusMessage.setText(R.string.headlines_row_top_changed);
@@ -259,6 +183,13 @@ public class ArticleFragment extends androidx.fragment.app.Fragment {
} else {
noteContainer.setVisibility(View.GONE);
}
+
+ note.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ m_activity.editArticleNote(m_article);
+ }
+ });
}
TextView dv = view.findViewById(R.id.date);
@@ -336,8 +267,6 @@ public class ArticleFragment extends androidx.fragment.app.Fragment {
}
});
- m_web.setVisibility(View.VISIBLE);
-
renderContent(savedInstanceState);
return view;
@@ -385,8 +314,6 @@ public class ArticleFragment extends androidx.fragment.app.Fragment {
ws.setJavaScriptEnabled(false);
- m_chromeClient = new FSVideoChromeClient(getView());
- m_web.setWebChromeClient(m_chromeClient);
m_web.setBackgroundColor(Color.TRANSPARENT);
ws.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
@@ -486,30 +413,6 @@ public class ArticleFragment extends androidx.fragment.app.Fragment {
if (m_web != null) m_web.onResume();
}
- public boolean inCustomView() {
- return (m_customView != null);
- }
-
- @Override
- public void onStop() {
- super.onStop();
-
- if (inCustomView()) {
- hideCustomView();
- }
- }
-
- public void hideCustomView() {
- if (m_chromeClient != null) {
- m_chromeClient.onHideCustomView();
- }
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- }
-
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticlePager.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticlePager.java
index c94f0c3a..445f94bb 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticlePager.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticlePager.java
@@ -6,7 +6,6 @@ import android.content.SharedPreferences;
import android.os.BadParcelableException;
import android.os.Bundle;
import android.os.Handler;
-import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
@@ -14,9 +13,10 @@ 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 androidx.fragment.app.FragmentActivity;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
+import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.snackbar.Snackbar;
import com.google.gson.JsonElement;
@@ -31,7 +31,7 @@ import java.util.HashMap;
public class ArticlePager extends androidx.fragment.app.Fragment {
private final String TAG = "ArticlePager";
- private PagerAdapter m_adapter;
+ private RecyclerView.Adapter m_adapter;
private HeadlinesEventListener m_listener;
protected Article m_article;
protected ArticleList m_articles = new ArticleList(); //m_articles = Application.getInstance().m_loadedArticles;
@@ -42,29 +42,18 @@ public class ArticlePager extends androidx.fragment.app.Fragment {
protected int m_firstId = 0;
private boolean m_refreshInProgress;
private boolean m_lazyLoadDisabled;
+ private ViewPager2 m_pager;
- private class PagerAdapter extends FragmentStatePagerAdapter {
+ private class PagerAdapter extends FragmentStateAdapter {
- public PagerAdapter(FragmentManager fm) {
- super(fm);
+ public PagerAdapter(FragmentActivity fa) {
+ super(fa);
}
private ArticleFragment m_currentFragment;
- // 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) {
+ public Fragment createFragment(int position) {
try {
Article article = m_articles.get(position);
@@ -82,7 +71,7 @@ public class ArticlePager extends androidx.fragment.app.Fragment {
}
@Override
- public int getCount() {
+ public int getItemCount() {
return m_articles.size();
}
@@ -90,13 +79,6 @@ public class ArticlePager extends androidx.fragment.app.Fragment {
return m_currentFragment;
}
- @Override
- public void setPrimaryItem(ViewGroup container, int position, Object object) {
- m_currentFragment = ((ArticleFragment) object);
-
- super.setPrimaryItem(container, position, object);
- }
-
}
public void initialize(Article article, Feed feed, ArticleList articles) {
@@ -125,7 +107,6 @@ public class ArticlePager extends androidx.fragment.app.Fragment {
if (savedInstanceState != null) {
m_article = savedInstanceState.getParcelable("m_article");
- //m_articles = savedInstanceState.getParcelable("m_articles");
m_feed = savedInstanceState.getParcelable("m_feed");
m_firstId = savedInstanceState.getInt("m_firstId");
}
@@ -136,30 +117,26 @@ public class ArticlePager extends androidx.fragment.app.Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_article_pager, container, false);
-
+
if (savedInstanceState != null) {
if (m_activity instanceof DetailActivity) {
m_articles = ((DetailActivity)m_activity).m_articles;
}
}
- m_adapter = new PagerAdapter(getActivity().getSupportFragmentManager());
+ m_adapter = new PagerAdapter(getActivity());
- ViewPager pager = view.findViewById(R.id.article_pager);
-
+ m_pager = view.findViewById(R.id.article_pager);
+
int position = m_articles.indexOf(m_article);
m_listener.onArticleSelected(m_article, false);
- pager.setAdapter(m_adapter);
-
- pager.setCurrentItem(position);
- pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
-
- }
+ m_pager.setAdapter(m_adapter);
+ m_pager.setOffscreenPageLimit(3);
+ m_pager.setCurrentItem(position, false);
+ m_pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
Log.d(TAG, "onPageSelected: " + position);
@@ -178,7 +155,7 @@ public class ArticlePager extends androidx.fragment.app.Fragment {
//Log.d(TAG, "Page #" + position + "/" + m_adapter.getCount());
- if (!m_refreshInProgress && !m_lazyLoadDisabled && (m_activity.isSmallScreen() || m_activity.isPortrait()) && position >= m_adapter.getCount() - 5) {
+ if (!m_refreshInProgress && !m_lazyLoadDisabled && (m_activity.isSmallScreen() || m_activity.isPortrait()) && position >= m_adapter.getItemCount() - 5) {
Log.d(TAG, "loading more articles...");
new Handler().postDelayed(new Runnable() {
@@ -190,11 +167,6 @@ public class ArticlePager extends androidx.fragment.app.Fragment {
}
}
}
-
- @Override
- public void onPageScrollStateChanged(int state) {
-
- }
});
return view;
@@ -220,9 +192,7 @@ public class ArticlePager extends androidx.fragment.app.Fragment {
if (isDetached() || !isAdded()) return;
if (!append) {
- ViewPager pager = getView().findViewById(R.id.article_pager);
- pager.setCurrentItem(0);
-
+ m_pager.setCurrentItem(0, false);
m_articles.clear();
}
@@ -390,9 +360,7 @@ public class ArticlePager extends androidx.fragment.app.Fragment {
int position = m_articles.indexOf(m_article);
- ViewPager pager = getView().findViewById(R.id.article_pager);
-
- pager.setCurrentItem(position);
+ m_pager.setCurrentItem(position);
}
}
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..06f18667 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
@@ -3,7 +3,6 @@ package org.fox.ttrss;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.TypedValue;
-import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CompoundButton;
@@ -13,8 +12,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 +20,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/CommonActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/CommonActivity.java
index 0ce80cb2..d93a52d3 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/CommonActivity.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/CommonActivity.java
@@ -28,7 +28,6 @@ import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.util.TypedValue;
import android.view.Display;
import android.view.View;
import android.widget.CheckBox;
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/DetailActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/DetailActivity.java
index 0edd6c10..c9da82da 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/DetailActivity.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/DetailActivity.java
@@ -10,12 +10,14 @@ import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
+import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.FragmentTransaction;
+import com.google.android.material.bottomappbar.BottomAppBar;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import org.fox.ttrss.types.Article;
@@ -25,6 +27,7 @@ import org.fox.ttrss.types.Feed;
public class DetailActivity extends OnlineActivity implements HeadlinesEventListener {
private final String TAG = this.getClass().getSimpleName();
protected ArticleList m_articles = new ArticleList();
+ protected BottomAppBar m_bottomAppBar;
protected SharedPreferences m_prefs;
private Article m_activeArticle;
@@ -68,6 +71,52 @@ public class DetailActivity extends OnlineActivity implements HeadlinesEventList
headlines.setVisibility(View.GONE);
}
+ m_bottomAppBar = findViewById(R.id.detail_bottom_appbar);
+
+ if (m_bottomAppBar != null) {
+ m_bottomAppBar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+
+ final ArticlePager ap = (ArticlePager) getSupportFragmentManager().findFragmentByTag(FRAG_ARTICLE);
+ final HeadlinesFragment hf = (HeadlinesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES);
+
+ Article article = ap.getSelectedArticle();
+
+ if (article == null) return false;
+
+ int itemId = item.getItemId();
+
+ if (itemId == R.id.article_set_labels) {
+ editArticleLabels(article);
+
+ return true;
+ } else if (itemId == R.id.toggle_attachments) {
+ displayAttachments(article);
+
+ return true;
+ } else if (itemId == R.id.article_edit_note) {
+ editArticleNote(article);
+
+ return true;
+ } else if (itemId == R.id.article_set_score) {
+ setArticleScore(article);
+
+ return true;
+ } else if (itemId == R.id.toggle_unread) {
+ article.unread = !article.unread;
+ saveArticleUnread(article);
+
+ if (hf != null) {
+ hf.notifyUpdated();
+ }
+ }
+
+ return false;
+ }
+ });
+ }
+
FloatingActionButton fab = findViewById(R.id.detail_fab);
if (fab != null && m_prefs.getBoolean("enable_article_fab", true)) {
@@ -136,11 +185,50 @@ public class DetailActivity extends OnlineActivity implements HeadlinesEventList
if (feed != null)
setTitle(feed.title);
+
+ initBottomBarMenu();
+ }
+ }
+ }
+
+ @Override
+ public void invalidateOptionsMenu() {
+ super.invalidateOptionsMenu();
+
+ initBottomBarMenu();
+ }
+
+ protected void initBottomBarMenu() {
+ if (m_bottomAppBar != null) {
+ Menu menu = m_bottomAppBar.getMenu();
+
+ menu.findItem(R.id.article_set_labels).setEnabled(getApiLevel() >= 1);
+ menu.findItem(R.id.article_edit_note).setEnabled(getApiLevel() >= 1);
+
+ final ArticlePager ap = (ArticlePager) getSupportFragmentManager().findFragmentByTag(FRAG_ARTICLE);
+
+ if (ap != null) {
+ Article article = ap.getSelectedArticle();
+
+ if (article != null) {
+ if (article.score > 0) {
+ menu.findItem(R.id.article_set_score).setIcon(R.drawable.baseline_trending_up_24);
+ } else if (article.score < 0) {
+ menu.findItem(R.id.article_set_score).setIcon(R.drawable.baseline_trending_down_24);
+ } else {
+ menu.findItem(R.id.article_set_score).setIcon(R.drawable.baseline_trending_flat_24);
+ }
+
+ menu.findItem(R.id.toggle_unread).setIcon(article.unread ? R.drawable.baseline_mark_email_unread_24 :
+ R.drawable.baseline_email_24);
+
+ menu.findItem(R.id.toggle_attachments).setVisible(article.attachments != null && article.attachments.size() > 0);
+ }
}
}
}
- @Override
+ @Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -197,30 +285,13 @@ public class DetailActivity extends OnlineActivity implements HeadlinesEventList
if (m_menu != null && getSessionId() != null) {
m_menu.setGroupVisible(R.id.menu_group_feeds, false);
- //HeadlinesFragment hf = (HeadlinesFragment)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());
m_menu.findItem(R.id.headlines_toggle_sort_order).setVisible(false);
ArticlePager af = (ArticlePager) getSupportFragmentManager().findFragmentByTag(FRAG_ARTICLE);
m_menu.setGroupVisible(R.id.menu_group_article, af != null);
-
- if (af != null) {
- if (af.getSelectedArticle() != null && af.getSelectedArticle().attachments != null && af.getSelectedArticle().attachments.size() > 0) {
- /* if (!isCompatMode() && (isSmallScreen() || !isPortrait())) {
- m_menu.findItem(R.id.toggle_attachments).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- } */
- m_menu.findItem(R.id.toggle_attachments).setVisible(true);
- } else {
- /* if (!isCompatMode()) {
- m_menu.findItem(R.id.toggle_attachments).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- } */
- m_menu.findItem(R.id.toggle_attachments).setVisible(false);
- }
- }
-
+
m_menu.findItem(R.id.search).setVisible(false);
}
}
@@ -278,7 +349,6 @@ public class DetailActivity extends OnlineActivity implements HeadlinesEventList
//Application.getInstance().m_activeArticle = article;
invalidateOptionsMenu();
-
}
public void showSidebar(boolean show) {
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryActivity.java
index ef3797b3..7868c6af 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryActivity.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryActivity.java
@@ -3,7 +3,6 @@ package org.fox.ttrss;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
-import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
@@ -14,12 +13,8 @@ import android.view.Window;
import android.widget.PopupMenu;
import android.widget.ProgressBar;
-import androidx.activity.EdgeToEdge;
-import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
-import androidx.core.graphics.Insets;
-import androidx.core.view.ViewCompat;
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;
@@ -51,7 +46,7 @@ public class GalleryActivity extends CommonActivity {
protected String m_title;
private ArticleImagesPagerAdapter m_adapter;
public String m_content;
- private ViewPager m_pager;
+ private ViewPager m_pager; // TODO replace with viewpager2
private ProgressBar m_checkProgress;
private static class ArticleImagesPagerAdapter extends FragmentStatePagerAdapter {
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java
index b6953bc6..352ebab6 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java
@@ -68,7 +68,6 @@ import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
import com.bumptech.glide.request.target.Target;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-import com.google.android.material.divider.MaterialDividerItemDecoration;
import com.google.android.material.snackbar.Snackbar;
import com.google.gson.JsonElement;
@@ -157,10 +156,10 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
if (article == null) return false;
int itemId = item.getItemId();
- if (itemId == R.id.set_labels) {
+ if (itemId == R.id.article_set_labels) {
m_activity.editArticleLabels(article);
return true;
- } else if (itemId == R.id.article_set_note) {
+ } else if (itemId == R.id.article_edit_note) {
m_activity.editArticleNote(article);
return true;
} else if (itemId == R.id.headlines_article_unread) {
@@ -268,8 +267,8 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
getActivity().getMenuInflater().inflate(R.menu.context_headlines, menu);
- menu.findItem(R.id.set_labels).setEnabled(m_activity.getApiLevel() >= 1);
- menu.findItem(R.id.article_set_note).setEnabled(m_activity.getApiLevel() >= 1);
+ menu.findItem(R.id.article_set_labels).setEnabled(m_activity.getApiLevel() >= 1);
+ menu.findItem(R.id.article_edit_note).setEnabled(m_activity.getApiLevel() >= 1);
super.onCreateContextMenu(menu, v, menuInfo);
}
@@ -358,12 +357,12 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
m_list.setLayoutManager(m_layoutManager);
m_list.setItemAnimator(new DefaultItemAnimator());
- if (m_compactLayoutMode) {
+ /* if (m_compactLayoutMode) {
MaterialDividerItemDecoration materialDivider = new MaterialDividerItemDecoration(m_list.getContext(), m_layoutManager.getOrientation());
materialDivider.setDividerInsetStart(dpToPx(80));
m_list.addItemDecoration(materialDivider);
- }
+ } */
ArticleListAdapter adapter = new ArticleListAdapter(getActivity(), R.layout.headlines_row, m_articles);
@@ -795,7 +794,6 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
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);
headlineHeader = v.findViewById(R.id.headline_header);
@@ -1191,6 +1189,12 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
holder.excerptView.setTextSize(TypedValue.COMPLEX_UNIT_SP, headlineFontSize);
holder.excerptView.setText(excerpt);
+ if (!excerpt.isEmpty()) {
+ holder.excerptView.setVisibility(View.VISIBLE);
+ } else {
+ holder.excerptView.setVisibility(View.GONE);
+ }
+
if (!canShowFlavorImage()) {
holder.excerptView.setPadding(holder.excerptView.getPaddingLeft(),
0,
@@ -1531,8 +1535,8 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.context_headlines, popup.getMenu());
- popup.getMenu().findItem(R.id.set_labels).setEnabled(m_activity.getApiLevel() >= 1);
- popup.getMenu().findItem(R.id.article_set_note).setEnabled(m_activity.getApiLevel() >= 1);
+ popup.getMenu().findItem(R.id.article_set_labels).setEnabled(m_activity.getApiLevel() >= 1);
+ popup.getMenu().findItem(R.id.article_edit_note).setEnabled(m_activity.getApiLevel() >= 1);
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/LogcatActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/LogcatActivity.java
index 60fad0ba..22db9e08 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/LogcatActivity.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/LogcatActivity.java
@@ -7,7 +7,6 @@ import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.ListView;
-import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@@ -25,7 +24,6 @@ public class LogcatActivity extends CommonActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
- getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
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 f06c9a7c..2e73af7f 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;
@@ -27,9 +24,9 @@ import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
+import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.Toolbar;
-import androidx.appcompat.app.AlertDialog;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.gson.Gson;
@@ -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();
- }
- }
-
- 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();
+ m_headlinesActionModeCallback = new HeadlinesActionModeCallback();
}
- 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,16 +411,10 @@ 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_set_note) {
+ } else if (itemId == R.id.article_edit_note) {
if (ap != null && ap.getSelectedArticle() != null) {
editArticleNote(ap.getSelectedArticle());
}
@@ -859,7 +723,7 @@ public class OnlineActivity extends CommonActivity {
}
return true;
- } else if (itemId == R.id.set_labels) {
+ } else if (itemId == R.id.article_set_labels) {
if (ap != null && ap.getSelectedArticle() != null) {
if (getApiLevel() != 7) {
editArticleLabels(ap.getSelectedArticle());
@@ -937,27 +801,24 @@ public class OnlineActivity extends CommonActivity {
} */
public void editArticleNote(final Article article) {
- String note = "";
-
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this)
.setTitle(article.title);
final EditText topicEdit = new EditText(this);
- topicEdit.setText(note);
+ topicEdit.setText(article.note);
builder.setView(topicEdit);
- builder.setPositiveButton(R.string.article_set_note, new Dialog.OnClickListener() {
+ builder.setPositiveButton(R.string.article_edit_note, new Dialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
String note = topicEdit.getText().toString().trim();
saveArticleNote(article, note);
- article.published = true;
- article.note = note;
-
- saveArticlePublished(article);
-
+
HeadlinesFragment hf = (HeadlinesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES);
if (hf != null) hf.notifyUpdated();
+
+ ArticlePager ap = (ArticlePager) getSupportFragmentManager().findFragmentByTag(FRAG_ARTICLE);
+ if (ap != null) ap.notifyUpdated();
}
});
@@ -1058,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 {
@@ -1130,7 +961,7 @@ public class OnlineActivity extends CommonActivity {
ApiRequest req = new ApiRequest(getApplicationContext()) {
protected void onPostExecute(JsonElement result) {
//toast(R.string.article_set_unread);
- initMenu();
+ invalidateOptionsMenu();
}
};
@@ -1204,7 +1035,7 @@ public class OnlineActivity extends CommonActivity {
public void saveArticleNote(final Article article, final String note) {
ApiRequest req = new ApiRequest(getApplicationContext()) {
protected void onPostExecute(JsonElement result) {
- //
+ article.note = note;
}
};
@@ -1413,64 +1244,54 @@ public class OnlineActivity extends CommonActivity {
}
// this may be called after activity has been destroyed (i.e. long asynctask)
- // might as well prevent null pointers if menu items are missing
protected void initMenu() {
- try {
- if (m_menu != null) {
- if (getSessionId() != null) {
- m_menu.setGroupVisible(R.id.menu_group_logged_in, true);
- m_menu.setGroupVisible(R.id.menu_group_logged_out, false);
- } else {
- m_menu.setGroupVisible(R.id.menu_group_logged_in, false);
- m_menu.setGroupVisible(R.id.menu_group_logged_out, true);
- }
-
- 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);
+ if (m_menu != null) {
+ if (getSessionId() != null) {
+ m_menu.setGroupVisible(R.id.menu_group_logged_in, true);
+ m_menu.setGroupVisible(R.id.menu_group_logged_out, false);
+ } else {
+ m_menu.setGroupVisible(R.id.menu_group_logged_in, false);
+ m_menu.setGroupVisible(R.id.menu_group_logged_out, true);
+ }
- m_menu.findItem(R.id.set_labels).setEnabled(getApiLevel() >= 1);
- m_menu.findItem(R.id.article_set_note).setEnabled(getApiLevel() >= 1);
- m_menu.findItem(R.id.subscribe_to_feed).setEnabled(getApiLevel() >= 5);
+ 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);
- MenuItem search = m_menu.findItem(R.id.search);
- search.setEnabled(getApiLevel() >= 2);
+ m_menu.findItem(R.id.subscribe_to_feed).setEnabled(getApiLevel() >= 5);
- ArticlePager ap = (ArticlePager) getSupportFragmentManager().findFragmentByTag(FRAG_ARTICLE);
+ MenuItem search = m_menu.findItem(R.id.search);
+ search.setEnabled(getApiLevel() >= 2);
- if (ap != null) {
- Article article = ap.getSelectedArticle();
+ ArticlePager ap = (ArticlePager) getSupportFragmentManager().findFragmentByTag(FRAG_ARTICLE);
- if (article != null) {
- m_menu.findItem(R.id.toggle_marked).setIcon(article.marked ? R.drawable.baseline_star_24 :
- R.drawable.baseline_star_outline_24);
+ if (ap != null) {
+ Article article = ap.getSelectedArticle();
- m_menu.findItem(R.id.toggle_published).setIcon(article.published ? R.drawable.baseline_check_box_24 :
- R.drawable.baseline_rss_feed_24);
+ if (article != null) {
+ m_menu.findItem(R.id.toggle_marked).setIcon(article.marked ? R.drawable.baseline_star_24 :
+ R.drawable.baseline_star_outline_24);
- m_menu.findItem(R.id.toggle_unread).setIcon(article.unread ? R.drawable.baseline_mark_as_unread_24 :
- R.drawable.baseline_email_24);
- }
+ m_menu.findItem(R.id.toggle_published).setIcon(article.published ? R.drawable.baseline_check_box_24 :
+ R.drawable.baseline_rss_feed_24);
}
+ }
- HeadlinesFragment hf = (HeadlinesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES);
-
- if (hf != null && !m_forceDisableActionMode) {
- if (hf.getSelectedArticles().size() > 0) {
- if (m_headlinesActionMode == null) {
- m_headlinesActionMode = startSupportActionMode(m_headlinesActionModeCallback);
- }
+ HeadlinesFragment hf = (HeadlinesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES);
- m_headlinesActionMode.setTitle(String.valueOf(hf.getSelectedArticles().size()));
- } else if (hf.getSelectedArticles().size() == 0 && m_headlinesActionMode != null) {
- m_headlinesActionMode.finish();
+ if (hf != null && !m_forceDisableActionMode) {
+ if (hf.getSelectedArticles().size() > 0) {
+ if (m_headlinesActionMode == null) {
+ m_headlinesActionMode = startSupportActionMode(m_headlinesActionModeCallback);
}
- } else if (m_forceDisableActionMode && m_headlinesActionMode != null) {
+
+ m_headlinesActionMode.setTitle(String.valueOf(hf.getSelectedArticles().size()));
+ } else if (hf.getSelectedArticles().size() == 0 && m_headlinesActionMode != null) {
m_headlinesActionMode.finish();
}
+ } else if (m_forceDisableActionMode && m_headlinesActionMode != null) {
+ m_headlinesActionMode.finish();
}
- } catch (NullPointerException e) {
- e.printStackTrace();
}
}
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/PreferencesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/PreferencesFragment.java
index af4c6b44..6e4c10f5 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/PreferencesFragment.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/PreferencesFragment.java
@@ -6,7 +6,6 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OkHttpProgressGlideModule.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OkHttpProgressGlideModule.java
index 1a7c6786..91e0ecf8 100644
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OkHttpProgressGlideModule.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OkHttpProgressGlideModule.java
@@ -1,18 +1,32 @@
package org.fox.ttrss.glide;
-import java.io.*;
-import java.util.*;
-
import android.content.Context;
-import android.os.*;
+import android.os.Handler;
+import android.os.Looper;
-import com.bumptech.glide.*;
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.GlideModule;
-import okhttp3.*;
-import okio.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import okhttp3.HttpUrl;
+import okhttp3.Interceptor;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+import okio.Buffer;
+import okio.BufferedSource;
+import okio.ForwardingSource;
+import okio.Okio;
+import okio.Source;
public class OkHttpProgressGlideModule implements GlideModule {
@Override public void applyOptions(Context context, GlideBuilder builder) {
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/WrappingTarget.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/WrappingTarget.java
index da4a9d86..235acc3c 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/WrappingTarget.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/WrappingTarget.java
@@ -2,13 +2,13 @@ package org.fox.ttrss.glide;
import android.graphics.drawable.Drawable;
+import androidx.annotation.NonNull;
+
import com.bumptech.glide.request.Request;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SizeReadyCallback;
import com.bumptech.glide.request.target.Target;
-import androidx.annotation.NonNull;
-
public class WrappingTarget<Z> implements Target<Z> {
protected final @NonNull Target<? super Z> target;
public WrappingTarget(@NonNull Target<? super Z> target) {
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 7994b576..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.set_labels).setVisible(false);
- menu.findItem(R.id.article_set_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.set_labels).setVisible(false);
- popup.getMenu().findItem(R.id.article_set_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/DetailActivityScrollingViewBehavior.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/util/DetailActivityScrollingViewBehavior.java
index 85e8ae4b..27682b13 100644
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/util/DetailActivityScrollingViewBehavior.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/util/DetailActivityScrollingViewBehavior.java
@@ -6,15 +6,16 @@ import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.core.view.ViewCompat;
+
import com.google.android.material.appbar.AppBarLayout;
+import com.google.android.material.bottomappbar.BottomAppBar;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.List;
-import androidx.annotation.NonNull;
-import androidx.coordinatorlayout.widget.CoordinatorLayout;
-import androidx.core.view.ViewCompat;
-
public class DetailActivityScrollingViewBehavior extends AppBarLayout.ScrollingViewBehavior {
private SharedPreferences m_prefs;
@@ -29,7 +30,7 @@ public class DetailActivityScrollingViewBehavior extends AppBarLayout.ScrollingV
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return super.layoutDependsOn(parent, child, dependency) ||
- dependency instanceof FloatingActionButton;
+ dependency instanceof FloatingActionButton || dependency instanceof BottomAppBar;
}
@Override
@@ -54,6 +55,8 @@ public class DetailActivityScrollingViewBehavior extends AppBarLayout.ScrollingV
for (View view : dependencies) {
if (view instanceof FloatingActionButton) {
((FloatingActionButton) view).hide();
+ } else if (view instanceof BottomAppBar) {
+ ((BottomAppBar) view).performHide();
}
}
} else if (dy < 0) {
@@ -62,6 +65,8 @@ public class DetailActivityScrollingViewBehavior extends AppBarLayout.ScrollingV
for (View view : dependencies) {
if (view instanceof FloatingActionButton) {
((FloatingActionButton) view).show();
+ } else if (view instanceof BottomAppBar) {
+ ((BottomAppBar) view).performShow();
}
}
}
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/util/HeaderViewRecyclerAdapter.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/util/HeaderViewRecyclerAdapter.java
index 519fded5..fb2218c1 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/util/HeaderViewRecyclerAdapter.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/util/HeaderViewRecyclerAdapter.java
@@ -19,13 +19,13 @@ package org.fox.ttrss.util;
import android.view.View;
import android.view.ViewGroup;
+import androidx.recyclerview.widget.RecyclerView;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import androidx.recyclerview.widget.RecyclerView;
-
/**
* <p>
* RecyclerView adapter designed to wrap an existing adapter allowing the addition of
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/java/org/fox/ttrss/widget/WidgetUpdateService.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/widget/WidgetUpdateService.java
index b9ec704e..3e2d2eaf 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/widget/WidgetUpdateService.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/widget/WidgetUpdateService.java
@@ -14,6 +14,9 @@ import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.RemoteViews;
+import androidx.annotation.NonNull;
+import androidx.core.app.JobIntentService;
+
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -24,9 +27,6 @@ import org.fox.ttrss.util.SimpleLoginManager;
import java.util.HashMap;
-import androidx.annotation.NonNull;
-import androidx.core.app.JobIntentService;
-
public class WidgetUpdateService extends JobIntentService {
private final String TAG = this.getClass().getSimpleName();
private SharedPreferences m_prefs;
diff --git a/org.fox.ttrss/src/main/res/drawable/baseline_mark_as_unread_24.xml b/org.fox.ttrss/src/main/res/drawable/baseline_mark_as_unread_24.xml
deleted file mode 100644
index 94381df3..00000000
--- a/org.fox.ttrss/src/main/res/drawable/baseline_mark_as_unread_24.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
-
- <path android:fillColor="@android:color/white" android:pathData="M18.83,7h-2.6L10.5,4 4,7.4L4,17c-1.1,0 -2,-0.9 -2,-2L2,7.17c0,-0.53 0.32,-1.09 0.8,-1.34L10.5,2l7.54,3.83c0.43,0.23 0.73,0.7 0.79,1.17zM20,8L7,8c-1.1,0 -2,0.9 -2,2v9c0,1.1 0.9,2 2,2h13c1.1,0 2,-0.9 2,-2v-9c0,-1.1 -0.9,-2 -2,-2zM20,11.67L13.5,15 7,11.67L7,10l6.5,3.33L20,10v1.67z"/>
-
-</vector>
diff --git a/org.fox.ttrss/src/main/res/drawable/baseline_mark_email_unread_24.xml b/org.fox.ttrss/src/main/res/drawable/baseline_mark_email_unread_24.xml
new file mode 100644
index 00000000..929f5ece
--- /dev/null
+++ b/org.fox.ttrss/src/main/res/drawable/baseline_mark_email_unread_24.xml
@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
+
+ <path android:fillColor="@android:color/white" android:pathData="M22,8.98V18c0,1.1 -0.9,2 -2,2H4c-1.1,0 -2,-0.9 -2,-2V6c0,-1.1 0.9,-2 2,-2h10.1C14.04,4.32 14,4.66 14,5c0,1.48 0.65,2.79 1.67,3.71L12,11L4,6v2l8,5l5.3,-3.32C17.84,9.88 18.4,10 19,10C20.13,10 21.16,9.61 22,8.98zM16,5c0,1.66 1.34,3 3,3s3,-1.34 3,-3s-1.34,-3 -3,-3S16,3.34 16,5z"/>
+
+</vector>
diff --git a/org.fox.ttrss/src/main/res/drawable/baseline_new_label_24.xml b/org.fox.ttrss/src/main/res/drawable/baseline_new_label_24.xml
new file mode 100644
index 00000000..3eb7690c
--- /dev/null
+++ b/org.fox.ttrss/src/main/res/drawable/baseline_new_label_24.xml
@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
+
+ <path android:fillColor="@android:color/white" android:pathData="M21,12l-4.37,6.16C16.26,18.68 15.65,19 15,19h-3l0,-6H9v-3H3V7c0,-1.1 0.9,-2 2,-2h10c0.65,0 1.26,0.31 1.63,0.84L21,12zM10,15H7v-3H5v3H2v2h3v3h2v-3h3V15z"/>
+
+</vector>
diff --git a/org.fox.ttrss/src/main/res/drawable/baseline_note_add_24.xml b/org.fox.ttrss/src/main/res/drawable/baseline_note_add_24.xml
new file mode 100644
index 00000000..e1ffd854
--- /dev/null
+++ b/org.fox.ttrss/src/main/res/drawable/baseline_note_add_24.xml
@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
+
+ <path android:fillColor="@android:color/white" android:pathData="M14,2L6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6zM16,16h-3v3h-2v-3L8,16v-2h3v-3h2v3h3v2zM13,9L13,3.5L18.5,9L13,9z"/>
+
+</vector>
diff --git a/org.fox.ttrss/src/main/res/layout-sw600dp-land/activity_detail.xml b/org.fox.ttrss/src/main/res/layout-sw600dp-land/activity_detail.xml
index 09534bc7..3078f77e 100644
--- a/org.fox.ttrss/src/main/res/layout-sw600dp-land/activity_detail.xml
+++ b/org.fox.ttrss/src/main/res/layout-sw600dp-land/activity_detail.xml
@@ -57,14 +57,22 @@
app:layout_behavior=".util.DetailActivityScrollingViewBehavior"
android:layout_height="match_parent"/>
+ <com.google.android.material.bottomappbar.BottomAppBar
+ android:id="@+id/detail_bottom_appbar"
+ app:backgroundTint="?colorSurfaceContainerHigh"
+ android:layout_width="match_parent"
+ android:layout_height="64dp"
+ android:layout_gravity="bottom"
+ app:menu="@menu/bottombar_detail" />
+
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/detail_fab"
+ android:layout_gravity="end|bottom"
+ android:layout_marginEnd="16dp"
+ android:layout_marginBottom="38dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="end|bottom"
- android:visibility="gone"
- android:src="@drawable/baseline_open_in_browser_24"
- android:layout_margin="16dp" />
+ app:srcCompat="@drawable/baseline_open_in_browser_24" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>
diff --git a/org.fox.ttrss/src/main/res/layout/fragment_article.xml b/org.fox.ttrss/src/main/res/layout/fragment_article.xml
index e75980b0..eba96d75 100755
--- a/org.fox.ttrss/src/main/res/layout/fragment_article.xml
+++ b/org.fox.ttrss/src/main/res/layout/fragment_article.xml
@@ -1,157 +1,145 @@
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.otaliastudios.nestedscrollcoordinatorlayout.NestedScrollCoordinatorLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/article_fragment"
- android:layout_width="fill_parent"
android:background="?colorSurfaceContainer"
+ android:layout_width="match_parent"
android:layout_height="match_parent">
- <FrameLayout
- android:id="@+id/article_fullscreen_video"
- android:visibility="invisible"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"/>
-
- <com.otaliastudios.nestedscrollcoordinatorlayout.NestedScrollCoordinatorLayout
+ <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
+ android:background="?colorSurfaceContainer"
android:layout_height="wrap_content">
- <com.google.android.material.appbar.AppBarLayout
+ <com.google.android.material.card.MaterialCardView
+ app:layout_scrollFlags="scroll|enterAlways"
+ app:strokeWidth="0dp"
+ app:shapeAppearance="@style/ShapeAppearanceArticleHeader"
android:layout_width="match_parent"
- android:background="?colorSurfaceContainer"
- android:layout_height="match_parent">
+ android:layout_height="wrap_content">
- <com.google.android.material.card.MaterialCardView
- app:layout_scrollFlags="scroll|enterAlways"
- app:strokeWidth="0dp"
- app:shapeAppearance="@style/ShapeAppearanceArticleHeader"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ <LinearLayout
+ android:id="@+id/article_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
<LinearLayout
- android:id="@+id/article_header"
+ android:orientation="horizontal"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:layout_height="match_parent">
- <LinearLayout
- android:orientation="horizontal"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
+ <TextView
+ android:id="@+id/title"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textColor="?colorPrimary"
+ tools:text="Unreasonably long article title blah blah blah blah blah blah"
+ android:textSize="18sp"
+ android:gravity="start" />
- <TextView
- android:id="@+id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:textColor="?colorPrimary"
- tools:text="Unreasonably long article title blah blah blah blah blah blah"
- android:textSize="18sp"
- android:gravity="start" />
+ </LinearLayout>
- </LinearLayout>
+ <TextView
+ android:id="@+id/comments"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ tools:text="comments"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAlignment="viewStart"
+ android:layout_weight="1"
+ android:fontFamily="sans-serif-light"
+ android:layout_marginTop="8dp"
+ android:textColor="?colorPrimary"
+ android:textSize="12sp" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginBottom="8dp"
+ android:layout_marginTop="8dp">
<TextView
- android:id="@+id/comments"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
- tools:text="comments"
- android:layout_width="match_parent"
+ android:id="@+id/tags"
+ tools:text="alpha, beta, gamma"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
+ android:layout_weight="0.7"
+ android:ellipsize="middle"
android:textAlignment="viewStart"
- android:layout_weight="1"
+ android:singleLine="true"
android:fontFamily="sans-serif-light"
- android:layout_marginTop="8dp"
- android:textColor="?colorPrimary"
+ android:textColor="?colorSecondary"
android:textSize="12sp" />
- <LinearLayout
- android:layout_width="match_parent"
+ <TextView
+ android:id="@+id/date"
+ tools:text="Jan 01, 1970"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
- android:layout_marginBottom="8dp"
- android:layout_marginTop="8dp">
-
- <TextView
- android:id="@+id/tags"
- tools:text="alpha, beta, gamma"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="0.7"
- android:ellipsize="middle"
- android:textAlignment="viewStart"
- android:singleLine="true"
- android:fontFamily="sans-serif-light"
- android:textColor="?colorSecondary"
- android:textSize="12sp" />
-
- <TextView
- android:id="@+id/date"
- tools:text="Jan 01, 1970"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="0.3"
- android:textAlignment="viewEnd"
- android:fontFamily="sans-serif-light"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?colorSecondary"
- android:textSize="12sp" />
-
- </LinearLayout>
-
- <LinearLayout
+ android:layout_weight="0.3"
+ android:textAlignment="viewEnd"
+ android:fontFamily="sans-serif-light"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?colorSecondary"
+ android:textSize="12sp" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <com.google.android.material.card.MaterialCardView
+ android:id="@+id/note_container"
android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ app:cardBackgroundColor="?colorTertiaryContainer"
+ android:layout_margin="8dp"
+ app:strokeWidth="0dp"
+ android:layout_height="match_parent">
- <com.google.android.material.card.MaterialCardView
- android:id="@+id/note_container"
+ <LinearLayout
android:layout_width="match_parent"
- app:cardBackgroundColor="?colorTertiaryContainer"
android:layout_margin="8dp"
- app:strokeWidth="0dp"
- android:layout_height="match_parent">
+ android:layout_height="wrap_content">
- <LinearLayout
+ <TextView
+ android:id="@+id/note"
+ tools:text="Article note (if any...)"
+ android:layout_gravity="center_vertical"
android:layout_width="match_parent"
- android:layout_margin="8dp"
- android:layout_height="wrap_content">
-
- <TextView
- android:id="@+id/note"
- tools:text="Article note (if any...)"
- android:layout_gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginEnd="8dp"
- android:textColor="?colorOnTertiaryContainer"
- android:layout_weight="1"
- android:textSize="12sp"/>
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- app:tint="?colorOnTertiaryContainer"
- android:src="@drawable/baseline_note_24"/>
-
- </LinearLayout>
- </com.google.android.material.card.MaterialCardView>
-
- </LinearLayout>
- </LinearLayout>
- </com.google.android.material.card.MaterialCardView>
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:textColor="?colorOnTertiaryContainer"
+ android:layout_weight="1"
+ android:textSize="12sp"/>
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ app:tint="?colorOnTertiaryContainer"
+ android:src="@drawable/baseline_note_24"/>
+
+ </LinearLayout>
+ </com.google.android.material.card.MaterialCardView>
- </com.google.android.material.appbar.AppBarLayout>
+ </LinearLayout>
+ </LinearLayout>
+ </com.google.android.material.card.MaterialCardView>
- <com.telefonica.nestedscrollwebview.NestedScrollWebView
- android:id="@+id/article_content"
- app:layout_behavior="@string/appbar_scrolling_view_behavior"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ </com.google.android.material.appbar.AppBarLayout>
- </com.otaliastudios.nestedscrollcoordinatorlayout.NestedScrollCoordinatorLayout>
+ <com.telefonica.nestedscrollwebview.NestedScrollWebView
+ android:id="@+id/article_content"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
-</FrameLayout> \ No newline at end of file
+</com.otaliastudios.nestedscrollcoordinatorlayout.NestedScrollCoordinatorLayout>
diff --git a/org.fox.ttrss/src/main/res/layout/fragment_article_pager.xml b/org.fox.ttrss/src/main/res/layout/fragment_article_pager.xml
index 1a687b1d..2f962418 100755
--- a/org.fox.ttrss/src/main/res/layout/fragment_article_pager.xml
+++ b/org.fox.ttrss/src/main/res/layout/fragment_article_pager.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<androidx.viewpager.widget.ViewPager
+<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/article_pager"
android:layout_width="match_parent"
diff --git a/org.fox.ttrss/src/main/res/layout/fragment_headlines_offline.xml b/org.fox.ttrss/src/main/res/layout/fragment_headlines_offline.xml
deleted file mode 100755
index 4ce8c1dd..00000000
--- a/org.fox.ttrss/src/main/res/layout/fragment_headlines_offline.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/headlines_fragment"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
- <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
- android:id="@+id/headlines_swipe_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <ListView
- android:id="@+id/headlines_list"
- android:background="?colorSurfaceContainer"
- android:drawSelectorOnTop="true"
- android:padding="8dp"
- android:dividerHeight="8dp"
- android:divider="@null"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
-
-</FrameLayout> \ No newline at end of file
diff --git a/org.fox.ttrss/src/main/res/layout/headlines_row_compact.xml b/org.fox.ttrss/src/main/res/layout/headlines_row_compact.xml
index fd328276..352aad91 100755
--- a/org.fox.ttrss/src/main/res/layout/headlines_row_compact.xml
+++ b/org.fox.ttrss/src/main/res/layout/headlines_row_compact.xml
@@ -4,21 +4,23 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/headlines_row"
- android:padding="@dimen/activity_horizontal_margin"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="8dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- tools:ignore="HardcodedText" >
+ android:orientation="horizontal">
<FrameLayout
- android:layout_marginRight="16dp"
- android:layout_gravity="center_vertical|left"
+ android:layout_gravity="center_vertical|start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp">
<ImageView
android:clickable="true"
+ android:focusable="true"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
@@ -36,7 +38,6 @@
<LinearLayout
android:layout_weight="1"
android:orientation="vertical"
- android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -44,94 +45,64 @@
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:textAlignment="viewStart"
android:maxLines="2"
android:ellipsize="end"
tools:text="Sample entry title"
android:textColor="?colorPrimary"
- android:textSize="18sp"
- android:layout_span="2" />
+ android:textSize="18sp" />
+
+ <TextView
+ android:id="@+id/feed_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="middle"
+ android:fontFamily="sans-serif-light"
+ android:singleLine="true"
+ tools:text="Example Feed AAA AAA AAAAAA AAAA AAAAA AA A A AA AA"
+ android:textColor="?colorSecondary"
+ android:textSize="12sp"
+ android:layout_marginTop="4dp" />
<TextView
android:id="@+id/excerpt"
android:maxLines="2"
- android:textAlignment="viewStart"
android:ellipsize="end"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
android:textColor="?colorSecondary"
android:textSize="13sp"
- android:layout_span="2"
- android:paddingTop="4dp" />
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
- <TextView
- android:id="@+id/feed_title"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:ellipsize="middle"
- android:fontFamily="sans-serif-light"
- android:gravity="center_vertical"
- android:singleLine="true"
- tools:text="Example Feed AAA AAA AAAAAA AAAA AAAAA AA A A AA AA"
- android:textAlignment="viewStart"
- android:textColor="?colorSecondary"
- android:textSize="12sp"
- android:layout_weight="0.5"
- android:paddingTop="4dp" />
-
- </LinearLayout>
-
+ android:layout_marginTop="4dp" />
</LinearLayout>
<LinearLayout
- android:id="@+id/headline_footer"
android:orientation="vertical"
android:layout_weight="0"
- android:layout_width="wrap_content"
+ android:layout_width="48dp"
android:layout_height="match_parent">
<TextView
android:id="@+id/date"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:singleLine="true"
android:ellipsize="none"
- android:layout_weight="1"
+ android:textAlignment="viewEnd"
+ android:layout_weight="0.5"
tools:text="Jan 01"
- android:textColor="?colorPrimary"
+ android:textColor="?colorSecondary"
android:textSize="12sp"
/>
-
<com.google.android.material.button.MaterialButton
android:id="@+id/marked"
style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content"
- android:layout_gravity="bottom|end"
- android:layout_height="wrap_content"
- android:layout_weight="0"
- android:clickable="true"
+ android:paddingEnd="0dp"
+ android:layout_gravity="end"
+ android:layout_height="24dp"
+ android:layout_weight="0.5"
app:icon="?ic_star_outline" />
-
</LinearLayout>
-
- <!-- <ImageView
- android:id="@+id/article_menu_button"
- android:layout_gravity="center"
- android:layout_width="wrap_content"
- android:layout_height="16dp"
- android:layout_weight="0"
- android:paddingLeft="4dp"
- android:paddingRight="4dp"
- android:src="@drawable/ic_action_overflow" /> -->
-
-
</LinearLayout> \ No newline at end of file
diff --git a/org.fox.ttrss/src/main/res/layout/headlines_row_compact_selected.xml b/org.fox.ttrss/src/main/res/layout/headlines_row_compact_selected.xml
index 6030df54..5721dcb8 100755
--- a/org.fox.ttrss/src/main/res/layout/headlines_row_compact_selected.xml
+++ b/org.fox.ttrss/src/main/res/layout/headlines_row_compact_selected.xml
@@ -4,16 +4,16 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/headlines_row"
- android:padding="@dimen/activity_horizontal_margin"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="8dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
android:background="?colorTertiaryContainer"
- android:textColor="?colorOnTertiaryContainer"
- tools:ignore="HardcodedText" >
+ android:orientation="horizontal">
<FrameLayout
- android:layout_marginRight="16dp"
android:layout_gravity="center_vertical|start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -21,6 +21,7 @@
<ImageView
android:clickable="true"
+ android:focusable="true"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
@@ -38,7 +39,6 @@
<LinearLayout
android:layout_weight="1"
android:orientation="vertical"
- android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -46,91 +46,63 @@
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:textAlignment="viewStart"
android:maxLines="2"
android:ellipsize="end"
tools:text="Sample entry title"
- android:textSize="18sp"
- android:layout_span="2" />
+ android:textColor="?colorOnTertiaryContainer"
+ android:textSize="18sp" />
+
+ <TextView
+ android:id="@+id/feed_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="middle"
+ android:fontFamily="sans-serif-light"
+ android:singleLine="true"
+ tools:text="Example Feed AAA AAA AAAAAA AAAA AAAAA AA A A AA AA"
+ android:textColor="?colorOnTertiaryContainer"
+ android:textSize="12sp"
+ android:layout_marginTop="4dp" />
<TextView
android:id="@+id/excerpt"
android:maxLines="2"
- android:textAlignment="viewStart"
android:ellipsize="end"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+ android:textColor="?colorOnTertiaryContainer"
android:textSize="13sp"
- android:layout_span="2"
- android:paddingTop="4dp" />
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
- <TextView
- android:id="@+id/feed_title"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:ellipsize="middle"
- android:fontFamily="sans-serif-light"
- android:gravity="center_vertical"
- android:singleLine="true"
- tools:text="Example Feed"
- android:textAlignment="viewStart"
- android:textSize="12sp"
- android:layout_weight="0.5"
- android:paddingTop="4dp" />
-
- </LinearLayout>
-
+ android:layout_marginTop="4dp" />
</LinearLayout>
<LinearLayout
- android:id="@+id/headline_footer"
android:orientation="vertical"
android:layout_weight="0"
- android:layout_width="wrap_content"
+ android:layout_width="48dp"
android:layout_height="match_parent">
<TextView
android:id="@+id/date"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:singleLine="true"
android:ellipsize="none"
- android:layout_weight="1"
+ android:textAlignment="viewEnd"
+ android:layout_weight="0.5"
tools:text="Jan 01"
android:textColor="?colorSecondary"
android:textSize="12sp"
/>
-
<com.google.android.material.button.MaterialButton
android:id="@+id/marked"
style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content"
- android:layout_gravity="bottom|end"
- android:layout_height="wrap_content"
- android:layout_weight="0"
- android:clickable="true"
+ android:paddingEnd="0dp"
+ android:layout_height="24dp"
+ android:layout_weight="0.5"
app:icon="?ic_star_outline" />
-
</LinearLayout>
-
- <!-- <ImageView
- android:id="@+id/article_menu_button"
- android:layout_gravity="center"
- android:layout_width="wrap_content"
- android:layout_height="16dp"
- android:layout_weight="0"
- android:paddingLeft="4dp"
- android:paddingRight="4dp"
- android:src="@drawable/ic_action_overflow" /> -->
-
-
</LinearLayout> \ No newline at end of file
diff --git a/org.fox.ttrss/src/main/res/layout/headlines_row_compact_selected_unread.xml b/org.fox.ttrss/src/main/res/layout/headlines_row_compact_selected_unread.xml
index 0d8d930d..06813e04 100755
--- a/org.fox.ttrss/src/main/res/layout/headlines_row_compact_selected_unread.xml
+++ b/org.fox.ttrss/src/main/res/layout/headlines_row_compact_selected_unread.xml
@@ -4,38 +4,41 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/headlines_row"
- android:padding="@dimen/activity_horizontal_margin"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="8dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
android:background="?colorTertiaryContainer"
- tools:ignore="HardcodedText" >
+ android:orientation="horizontal">
<FrameLayout
- android:layout_marginRight="8dp"
android:layout_gravity="center_vertical|start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginEnd="8dp">
+ android:layout_marginEnd="16dp">
<ImageView
android:clickable="true"
+ android:focusable="true"
android:layout_width="48dp"
android:layout_height="48dp"
+ android:layout_gravity="center"
android:id="@+id/text_image"/>
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/check_sm"
- android:id="@+id/text_checked"/>
+ android:id="@+id/text_checked"
+ android:layout_gravity="center" />
</FrameLayout>
<LinearLayout
android:layout_weight="1"
android:orientation="vertical"
- android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -43,89 +46,65 @@
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:textAlignment="viewStart"
android:maxLines="2"
android:ellipsize="end"
tools:text="Sample entry title"
+ android:textColor="?colorOnTertiaryContainer"
android:textStyle="bold"
- android:textSize="18sp"
- android:layout_span="2" />
+ android:textSize="18sp" />
+
+ <TextView
+ android:id="@+id/feed_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="middle"
+ android:fontFamily="sans-serif-light"
+ android:singleLine="true"
+ tools:text="Example Feed AAA AAA AAAAAA AAAA AAAAA AA A A AA AA"
+ android:textColor="?colorOnTertiaryContainer"
+ android:textSize="12sp"
+ android:layout_marginTop="4dp" />
<TextView
android:id="@+id/excerpt"
android:maxLines="2"
- android:textAlignment="viewStart"
android:ellipsize="end"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+ android:textColor="?colorOnTertiaryContainer"
android:textSize="13sp"
- android:layout_span="2"
- android:paddingTop="4dp" />
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
- <TextView
- android:id="@+id/feed_title"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:ellipsize="middle"
- android:fontFamily="sans-serif-light"
- android:gravity="center_vertical"
- android:singleLine="true"
- tools:text="Example Feed"
- android:textAlignment="viewStart"
- android:textSize="12sp"
- android:layout_weight="0.5"
- android:paddingTop="4dp" />
-
- </LinearLayout>
-
+ android:layout_marginTop="4dp" />
</LinearLayout>
<LinearLayout
- android:id="@+id/headline_footer"
android:orientation="vertical"
android:layout_weight="0"
- android:layout_width="wrap_content"
+ android:layout_width="48dp"
android:layout_height="match_parent">
<TextView
android:id="@+id/date"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:singleLine="true"
android:ellipsize="none"
- android:layout_weight="1"
+ android:textAlignment="viewEnd"
+ android:layout_weight="0.5"
tools:text="Jan 01"
android:textColor="?colorSecondary"
- android:textSize="12sp" />
+ android:textSize="12sp"
+ />
<com.google.android.material.button.MaterialButton
android:id="@+id/marked"
style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content"
- android:layout_gravity="bottom|end"
- android:layout_height="wrap_content"
- android:layout_weight="0"
+ android:paddingEnd="0dp"
+ android:layout_gravity="end"
+ android:layout_height="24dp"
+ android:layout_weight="0.5"
app:icon="?ic_star_outline" />
-
</LinearLayout>
-
- <!-- <ImageView
- android:id="@+id/article_menu_button"
- android:layout_gravity="center"
- android:layout_width="wrap_content"
- android:layout_height="16dp"
- android:layout_weight="0"
- android:paddingLeft="4dp"
- android:paddingRight="4dp"
- android:src="@drawable/ic_action_overflow" /> -->
-
-
</LinearLayout> \ No newline at end of file
diff --git a/org.fox.ttrss/src/main/res/layout/headlines_row_compact_unread.xml b/org.fox.ttrss/src/main/res/layout/headlines_row_compact_unread.xml
index 222d19d1..6aa1bdcd 100755
--- a/org.fox.ttrss/src/main/res/layout/headlines_row_compact_unread.xml
+++ b/org.fox.ttrss/src/main/res/layout/headlines_row_compact_unread.xml
@@ -4,15 +4,16 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/headlines_row"
- android:padding="@dimen/activity_horizontal_margin"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="8dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
android:background="?colorSurfaceContainerLowest"
- tools:ignore="HardcodedText" >
+ android:orientation="horizontal">
<FrameLayout
- android:layout_marginRight="16dp"
android:layout_gravity="center_vertical|start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -20,6 +21,7 @@
<ImageView
android:clickable="true"
+ android:focusable="true"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
@@ -37,7 +39,6 @@
<LinearLayout
android:layout_weight="1"
android:orientation="vertical"
- android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -45,78 +46,65 @@
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:textAlignment="viewStart"
android:maxLines="2"
android:ellipsize="end"
tools:text="Sample entry title"
android:textStyle="bold"
- android:textSize="18sp"
- android:layout_span="2" />
+ android:textSize="18sp" />
+
+ <TextView
+ android:id="@+id/feed_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="middle"
+ android:fontFamily="sans-serif-light"
+ android:singleLine="true"
+ tools:text="Example Feed AAA AAA AAAAAA AAAA AAAAA AA A A AA AA"
+ android:textColor="?colorSecondary"
+ android:textSize="12sp"
+ android:layout_marginTop="4dp" />
<TextView
android:id="@+id/excerpt"
android:maxLines="2"
- android:textAlignment="viewStart"
android:ellipsize="end"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+ android:textColor="?colorSecondary"
android:textSize="13sp"
- android:layout_span="2"
- android:paddingTop="4dp" />
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
- <TextView
- android:id="@+id/feed_title"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:ellipsize="middle"
- android:fontFamily="sans-serif-light"
- android:gravity="center_vertical"
- android:singleLine="true"
- tools:text="Example Feed AAA AAA AAAAAA AAAA AAAAA AA A A AA AA"
- android:textAlignment="viewStart"
- android:textSize="12sp"
- android:layout_weight="0.5"
- android:paddingTop="4dp" />
-
- </LinearLayout>
+ android:layout_marginTop="4dp" />
</LinearLayout>
<LinearLayout
- android:id="@+id/headline_footer"
android:orientation="vertical"
android:layout_weight="0"
- android:layout_width="wrap_content"
+ android:layout_width="48dp"
android:layout_height="match_parent">
<TextView
android:id="@+id/date"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
- android:textColor="?colorSecondary"
android:singleLine="true"
android:ellipsize="none"
- android:layout_weight="1"
+ android:textAlignment="viewEnd"
+ android:layout_weight="0.5"
tools:text="Jan 01"
- android:textSize="12sp" />
+ android:textColor="?colorSecondary"
+ android:textSize="12sp"
+ />
<com.google.android.material.button.MaterialButton
android:id="@+id/marked"
style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content"
- android:layout_gravity="bottom|end"
- android:layout_height="wrap_content"
- android:layout_weight="0"
+ android:paddingEnd="0dp"
+ android:layout_gravity="end"
+ android:layout_height="24dp"
+ android:layout_weight="0.5"
app:icon="?ic_star_outline" />
-
</LinearLayout>
-
</LinearLayout> \ No newline at end of file
diff --git a/org.fox.ttrss/src/main/res/layout/layout_detail_phone.xml b/org.fox.ttrss/src/main/res/layout/layout_detail_phone.xml
index 429b27c0..420b6f3a 100644
--- a/org.fox.ttrss/src/main/res/layout/layout_detail_phone.xml
+++ b/org.fox.ttrss/src/main/res/layout/layout_detail_phone.xml
@@ -2,16 +2,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <com.google.android.material.floatingactionbutton.FloatingActionButton
- android:id="@+id/detail_fab"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="end|bottom"
- android:visibility="gone"
- android:src="@drawable/baseline_open_in_browser_24"
- android:layout_margin="16dp" />
+ android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
@@ -25,7 +16,7 @@
android:id="@+id/article_fragment"
app:layout_behavior=".util.DetailActivityScrollingViewBehavior"
android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ android:layout_height="match_parent">
</FrameLayout>
<FrameLayout
@@ -35,5 +26,22 @@
android:layout_width="0dp">
</FrameLayout>
+ <com.google.android.material.bottomappbar.BottomAppBar
+ android:id="@+id/detail_bottom_appbar"
+ app:backgroundTint="?colorSurfaceContainerHigh"
+ android:layout_width="match_parent"
+ android:layout_height="64dp"
+ android:layout_gravity="bottom"
+ app:menu="@menu/bottombar_detail" />
+
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/detail_fab"
+ android:layout_gravity="end|bottom"
+ android:layout_marginEnd="16dp"
+ android:layout_marginBottom="38dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="@drawable/baseline_open_in_browser_24" />
+
</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/org.fox.ttrss/src/main/res/menu/action_mode_headlines.xml b/org.fox.ttrss/src/main/res/menu/action_mode_headlines.xml
index 35981c01..ccd2c266 100644
--- a/org.fox.ttrss/src/main/res/menu/action_mode_headlines.xml
+++ b/org.fox.ttrss/src/main/res/menu/action_mode_headlines.xml
@@ -4,7 +4,7 @@
android:id="@+id/selection_toggle_unread"
app:showAsAction="always"
app:iconTint="?attr/colorControlNormal"
- android:icon="@drawable/baseline_mark_as_unread_24"
+ android:icon="@drawable/baseline_mark_email_unread_24"
android:title="@string/selection_toggle_unread"/>
<item
diff --git a/org.fox.ttrss/src/main/res/menu/activity_main.xml b/org.fox.ttrss/src/main/res/menu/activity_main.xml
index 68dec353..1650f366 100755
--- a/org.fox.ttrss/src/main/res/menu/activity_main.xml
+++ b/org.fox.ttrss/src/main/res/menu/activity_main.xml
@@ -58,40 +58,14 @@
android:id="@+id/toggle_published"
android:icon="@drawable/baseline_rss_feed_24"
app:iconTint="?attr/colorControlNormal"
- android:title="@string/article_toggle_published"/>
- <item
- android:id="@+id/toggle_unread"
- android:icon="@drawable/baseline_email_24"
- app:iconTint="?attr/colorControlNormal"
app:showAsAction="ifRoom"
- android:title="@string/article_toggle_unread"/>
- <item
- android:id="@+id/toggle_attachments"
- android:icon="@drawable/baseline_attach_file_24"
- app:showAsAction=""
- android:title="@string/attachments_prompt"/>
+ android:title="@string/article_toggle_published"/>
<item
android:id="@+id/share_article"
android:icon="@drawable/baseline_share_24"
app:iconTint="?attr/colorControlNormal"
app:showAsAction="ifRoom"
android:title="@string/share_article"/>
- <item
- android:id="@+id/set_labels"
- app:showAsAction=""
- android:title="@string/article_set_labels"/>
- <item
- android:id="@+id/article_set_note"
- app:showAsAction=""
- android:title="@string/article_set_note"/>
- <item
- android:id="@+id/article_set_score"
- app:showAsAction=""
- android:title="@string/set_score"/>
-
- <item
- android:id="@+id/catchup_above"
- android:title="@string/article_mark_read_above"/>
</group>
diff --git a/org.fox.ttrss/src/main/res/menu/bottombar_detail.xml b/org.fox.ttrss/src/main/res/menu/bottombar_detail.xml
new file mode 100644
index 00000000..744ae79b
--- /dev/null
+++ b/org.fox.ttrss/src/main/res/menu/bottombar_detail.xml
@@ -0,0 +1,38 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <item
+ android:id="@+id/article_set_score"
+ app:showAsAction="always"
+ app:iconTint="?attr/colorControlNormal"
+ android:icon="@drawable/baseline_trending_flat_24"
+ android:title="@string/set_score"/>
+
+ <item
+ android:id="@+id/toggle_unread"
+ android:icon="@drawable/baseline_email_24"
+ app:iconTint="?attr/colorControlNormal"
+ app:showAsAction="always"
+ android:title="@string/article_toggle_unread"/>
+
+ <item
+ android:id="@+id/article_set_labels"
+ app:showAsAction="always"
+ android:icon="@drawable/baseline_new_label_24"
+ app:iconTint="?attr/colorControlNormal"
+ android:title="@string/article_set_labels"/>
+
+ <item
+ android:id="@+id/article_edit_note"
+ app:showAsAction="always"
+ android:icon="@drawable/baseline_note_add_24"
+ app:iconTint="?attr/colorControlNormal"
+ android:title="@string/article_edit_note"/>
+
+ <item
+ android:id="@+id/toggle_attachments"
+ android:icon="@drawable/baseline_attachment_24"
+ app:iconTint="?attr/colorControlNormal"
+ app:showAsAction="always"
+ android:title="@string/attachments_prompt"/>
+
+</menu> \ No newline at end of file
diff --git a/org.fox.ttrss/src/main/res/menu/context_headlines.xml b/org.fox.ttrss/src/main/res/menu/context_headlines.xml
index dffc9e47..e5a892ab 100644
--- a/org.fox.ttrss/src/main/res/menu/context_headlines.xml
+++ b/org.fox.ttrss/src/main/res/menu/context_headlines.xml
@@ -18,12 +18,12 @@
app:showAsAction=""
android:title="@string/article_mark_read_above"/>
<item
- android:id="@+id/set_labels"
+ android:id="@+id/article_set_labels"
android:title="@string/article_set_labels"/>
<item
- android:id="@+id/article_set_note"
+ android:id="@+id/article_edit_note"
app:showAsAction=""
- android:title="@string/article_set_note"/>
+ android:title="@string/article_edit_note"/>
<item
android:id="@+id/headlines_article_unread"
app:showAsAction=""
diff --git a/org.fox.ttrss/src/main/res/values/strings.xml b/org.fox.ttrss/src/main/res/values/strings.xml
index 0de65e12..6a67013a 100755
--- a/org.fox.ttrss/src/main/res/values/strings.xml
+++ b/org.fox.ttrss/src/main/res/values/strings.xml
@@ -106,7 +106,7 @@
<string name="dialog_offline_sync_in_progress">Offline sync in progress</string>
<string name="dialog_offline_sync_stop">Stop syncing</string>
<string name="dialog_offline_sync_continue">Continue</string>
- <string name="article_set_note">Publish with note</string>
+ <string name="article_edit_note">Edit note</string>
<string name="dialog_open_preferences">Settings</string>
<string name="dialog_need_configure_prompt">Please fill in your tt-rss server information such as URL, login, and password.</string>
<!-- <string name="update_headlines">Refresh</string> -->
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"