summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleModel.java2
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/BaseFeedlistFragment.java78
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/CommonActivity.java2
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/FeedCategoriesFragment.java446
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java356
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java13
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/MasterActivity.java149
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/OnlineActivity.java7
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/RootCategoriesFragment.java134
-rw-r--r--org.fox.ttrss/src/main/java/org/fox/ttrss/types/Feed.java84
-rw-r--r--org.fox.ttrss/src/main/res/drawable/baseline_label_24.xml5
-rwxr-xr-xorg.fox.ttrss/src/main/res/layout/feeds_row_header.xml70
-rwxr-xr-xorg.fox.ttrss/src/main/res/layout/fragment_feeds.xml96
-rwxr-xr-xorg.fox.ttrss/src/main/res/layout/fragment_feeds_recycler.xml18
-rwxr-xr-xorg.fox.ttrss/src/main/res/xml/preferences.xml6
15 files changed, 543 insertions, 923 deletions
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleModel.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleModel.java
index 80467f63..7a79887d 100644
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleModel.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleModel.java
@@ -80,7 +80,7 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle
}
public void startLoading(boolean append, @NonNull Feed feed, int resizeWidth) {
- Log.d(TAG, "startLoading append=" + append);
+ Log.d(TAG, "startLoading append=" + append + " feed id=" + feed.id + " cat=" + feed.is_cat);
m_resizeWidth = resizeWidth;
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
deleted file mode 100755
index 4f48a19e..00000000
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/BaseFeedlistFragment.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.fox.ttrss;
-
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import androidx.appcompat.widget.SwitchCompat;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-public abstract class BaseFeedlistFragment extends androidx.fragment.app.Fragment {
- abstract public void refresh();
-
- public void initDrawerHeader(LayoutInflater inflater, View view, ListView list, final CommonActivity activity, final SharedPreferences prefs) {
-
- View layout = inflater.inflate(R.layout.feeds_row_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);
-
- 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);
-
- settings.setOnClickListener(v -> {
- try {
- Intent intent = new Intent(getActivity(),
- PreferencesActivity.class);
-
- startActivityForResult(intent, 0);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- });
-
- /* deal with ~material~ footers */
-
- // divider
- final View footer = inflater.inflate(R.layout.feeds_row_divider, list, false);
- footer.setOnClickListener(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);
- icon.setImageResource(R.drawable.baseline_filter_alt_24);
-
- final SwitchCompat rowSwitch = rowToggle.findViewById(R.id.row_switch);
- rowSwitch.setChecked(activity.getUnreadOnly());
-
- rowSwitch.setOnCheckedChangeListener((button, isChecked) -> {
- activity.setUnreadOnly(isChecked);
- refresh();
- });
-
- footer.setOnClickListener(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 97e356c4..d5d593ae 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
@@ -310,7 +310,7 @@ public class CommonActivity extends AppCompatActivity implements SharedPreferenc
setAppTheme(sharedPreferences);
}
- String[] filter = new String[] { "enable_cats", "headline_mode", "widget_update_interval",
+ String[] filter = new String[] { "headline_mode", "widget_update_interval",
"headlines_swipe_to_dismiss", "headlines_mark_read_scroll", "headlines_request_size",
"force_phone_layout", "open_on_startup"};
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedCategoriesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedCategoriesFragment.java
deleted file mode 100755
index 34127013..00000000
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedCategoriesFragment.java
+++ /dev/null
@@ -1,446 +0,0 @@
-package org.fox.ttrss;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-import android.os.Bundle;
-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.ArrayAdapter;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import androidx.loader.app.LoaderManager;
-import androidx.loader.content.Loader;
-import androidx.preference.PreferenceManager;
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.reflect.TypeToken;
-
-import org.fox.ttrss.types.Feed;
-import org.fox.ttrss.types.FeedCategory;
-import org.fox.ttrss.types.FeedCategoryList;
-
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-
-public class FeedCategoriesFragment extends BaseFeedlistFragment implements OnItemClickListener, OnSharedPreferenceChangeListener,
- LoaderManager.LoaderCallbacks<JsonElement> {
- private final String TAG = this.getClass().getSimpleName();
- private FeedCategoryListAdapter m_adapter;
- private final FeedCategoryList m_cats = new FeedCategoryList();
- FeedCategory m_selectedCat;
- private MasterActivity m_activity;
- private SwipeRefreshLayout m_swipeLayout;
- private ListView m_list;
- protected SharedPreferences m_prefs;
-
- @Override
- public Loader<JsonElement> onCreateLoader(int id, Bundle args) {
- final String sessionId = m_activity.getSessionId();
- final boolean unreadOnly = m_activity.getUnreadOnly();
-
- HashMap<String, String> params = new HashMap<>();
- params.put("op", "getCategories");
- params.put("sid", sessionId);
- params.put("enable_nested", "true");
-
- if (unreadOnly)
- params.put("unread_only", "true");
-
- return new ApiLoader(getContext(), params);
- }
-
- @Override
- public void onLoadFinished(Loader<JsonElement> loader, JsonElement result) {
- Log.d(TAG, "onLoadFinished: " + loader + " " + result);
-
- if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false);
-
- if (result != null) {
- try {
- JsonArray content = result.getAsJsonArray();
- if (content != null) {
- Type listType = new TypeToken<List<FeedCategory>>() {}.getType();
- final List<FeedCategory> cats = new Gson().fromJson(content, listType);
-
- m_cats.clear();
-
- int apiLevel = m_activity.getApiLevel();
-
- boolean specialCatFound = false;
-
- // virtual cats implemented in getCategories since api level 1
- if (apiLevel == 0) {
- m_cats.add(new FeedCategory(-1, getString(R.string.cat_special), 0));
- m_cats.add(new FeedCategory(-2, getString(R.string.cat_labels), 0));
- m_cats.add(new FeedCategory(0, getString(R.string.cat_uncategorized), 0));
-
- specialCatFound = true;
- }
-
- for (FeedCategory c : cats) {
- if (c.id == -1) {
- specialCatFound = true;
- break;
- }
- }
-
- m_cats.addAll(cats);
-
- sortCats();
-
- if (!specialCatFound) {
- m_cats.add(0, new FeedCategory(-1, getString(R.string.cat_special), 0));
- }
-
- m_adapter.notifyDataSetChanged();
-
- return;
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- ApiLoader al = (ApiLoader) loader;
-
- if (al.getLastError() == ApiCommon.ApiError.LOGIN_FAILED) {
- m_activity.login(true);
- } else {
- if (al.getLastErrorMessage() != null) {
- m_activity.toast(getString(al.getErrorMessage()) + "\n" + al.getLastErrorMessage());
- } else {
- m_activity.toast(al.getErrorMessage());
- }
- }
- }
-
- public void sortCats() {
- Comparator<FeedCategory> cmp;
-
- if (m_prefs.getBoolean("sort_feeds_by_unread", false)) {
- cmp = new CatUnreadComparator();
- } else {
- if (m_activity.getApiLevel() >= 3) {
- cmp = new CatOrderComparator();
- } else {
- cmp = new CatTitleComparator();
- }
- }
-
- try {
- m_cats.sort(cmp);
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- }
- try {
- m_adapter.notifyDataSetChanged();
- } catch (NullPointerException e) {
- // adapter missing
- }
- }
-
- @Override
- public void onLoaderReset(Loader<JsonElement> loader) {
- Log.d(TAG, "onLoaderReset: " + loader);
-
- /*m_cats.clear();
- m_adapter.notifyDataSetChanged();*/
- }
-
- @SuppressLint("DefaultLocale")
- static class CatUnreadComparator implements Comparator<FeedCategory> {
- @Override
- public int compare(FeedCategory a, FeedCategory b) {
- if (a.unread != b.unread)
- return b.unread - a.unread;
- else
- return a.title.toUpperCase().compareTo(b.title.toUpperCase());
- }
- }
-
-
- @SuppressLint("DefaultLocale")
- static class CatTitleComparator implements Comparator<FeedCategory> {
-
- @Override
- public int compare(FeedCategory a, FeedCategory b) {
- if (a.id >= 0 && b.id >= 0)
- return a.title.toUpperCase().compareTo(b.title.toUpperCase());
- else
- return a.id - b.id;
- }
-
- }
-
- @SuppressLint("DefaultLocale")
- static class CatOrderComparator implements Comparator<FeedCategory> {
-
- @Override
- public int compare(FeedCategory a, FeedCategory b) {
- if (a.id >= 0 && b.id >= 0)
- if (a.order_id != 0 && b.order_id != 0)
- return a.order_id - b.order_id;
- else
- return a.title.toUpperCase().compareTo(b.title.toUpperCase());
- else
- return a.id - b.id;
- }
-
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
- .getMenuInfo();
-
- int itemId = item.getItemId();
- if (itemId == R.id.browse_headlines) {
- FeedCategory cat = getCategoryAtPosition(info.position);
- if (cat != null) {
- m_activity.onCatSelected(cat, true);
- //setSelectedCategory(cat);
- }
- return true;
- } else if (itemId == R.id.browse_feeds) {
- FeedCategory cat = getCategoryAtPosition(info.position);
- if (cat != null) {
- m_activity.onCatSelected(cat, false);
- //cf.setSelectedCategory(cat);
- }
- return true;
- } else if (itemId == R.id.catchup_category) {
- final FeedCategory cat = getCategoryAtPosition(info.position);
-
- if (cat != null) {
- m_activity.catchupDialog(new Feed(cat.id, cat.title, true));
- }
- return true;
- }
- Log.d(TAG, "onContextItemSelected, unhandled id=" + item.getItemId());
- return super.onContextItemSelected(item);
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
-
- m_activity.getMenuInflater().inflate(R.menu.context_category, menu);
-
- AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
- FeedCategory cat = (FeedCategory) m_list.getItemAtPosition(info.position);
-
- if (cat != null)
- menu.setHeaderTitle(cat.title);
-
- super.onCreateContextMenu(menu, v, menuInfo);
-
- }
-
- public FeedCategory getCategoryAtPosition(int position) {
- try {
- return (FeedCategory) m_list.getItemAtPosition(position);
- } catch (NullPointerException e) {
- return null;
- } catch (IndexOutOfBoundsException e) {
- return null;
- }
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- if (savedInstanceState != null) {
- m_selectedCat = savedInstanceState.getParcelable("m_selectedCat");
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-
- View view = inflater.inflate(R.layout.fragment_feeds, container, false);
-
- m_swipeLayout = view.findViewById(R.id.feeds_swipe_container);
-
- m_swipeLayout.setOnRefreshListener(this::refresh);
-
- m_list = view.findViewById(R.id.feeds);
- m_adapter = new FeedCategoryListAdapter(getActivity(), R.layout.feeds_row, m_cats);
-
- initDrawerHeader(inflater, view, m_list, m_activity, m_prefs);
-
- m_list.setAdapter(m_adapter);
- m_list.setOnItemClickListener(this);
- registerForContextMenu(m_list);
-
- return view;
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
-
- m_activity = (MasterActivity)activity;
-
- m_prefs = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext());
- m_prefs.registerOnSharedPreferenceChangeListener(this);
-
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- LoaderManager.getInstance(this).initLoader(Application.LOADER_CATS, null, this).forceLoad();
-
- m_activity.invalidateOptionsMenu();
- }
-
- public void refresh() {
- if (!isAdded())
- return;
-
- if (m_swipeLayout != null)
- m_swipeLayout.setRefreshing(true);
-
- LoaderManager.getInstance(this).restartLoader(Application.LOADER_CATS, null, this).forceLoad();
- }
-
- private class FeedCategoryListAdapter extends ArrayAdapter<FeedCategory> {
- private final ArrayList<FeedCategory> items;
-
- public static final int VIEW_NORMAL = 0;
- public static final int VIEW_SELECTED = 1;
-
- public static final int VIEW_COUNT = VIEW_SELECTED+1;
-
- public FeedCategoryListAdapter(Context context, int textViewResourceId, ArrayList<FeedCategory> items) {
- super(context, textViewResourceId, items);
- this.items = items;
- }
-
- public int getViewTypeCount() {
- return VIEW_COUNT;
- }
-
- @Override
- public int getItemViewType(int position) {
- FeedCategory cat = items.get(position);
-
- if (/*!m_activity.isSmallScreen() &&*/ m_selectedCat != null && cat.id == m_selectedCat.id) {
- return VIEW_SELECTED;
- } else {
- return VIEW_NORMAL;
- }
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View v = convertView;
-
- FeedCategory cat = items.get(position);
-
- if (v == null) {
- int layoutId = R.layout.feeds_row;
-
- if (getItemViewType(position) == VIEW_SELECTED) {
- layoutId = R.layout.feeds_row_selected;
- }
-
- LayoutInflater vi = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- v = vi.inflate(layoutId, null);
-
- }
-
- ImageView icon = v.findViewById(R.id.icon);
-
- if (icon != null) {
- icon.setImageResource(R.drawable.baseline_folder_open_24);
-
- }
-
- TextView tt = v.findViewById(R.id.title);
-
- if (tt != null) {
- tt.setText(cat.title);
- }
-
- TextView tu = v.findViewById(R.id.unread_counter);
-
- if (tu != null) {
- tu.setText(String.valueOf(cat.unread));
- tu.setVisibility((cat.unread > 0) ? View.VISIBLE : View.INVISIBLE);
- }
-
- return v;
- }
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
- String key) {
-
- sortCats();
-
- }
-
- @Override
- public void onItemClick(AdapterView<?> av, View view, int position, long id) {
- ListView list = (ListView)av;
-
- Log.d(TAG, "onItemClick=" + position);
-
- if (list != null) {
-
- FeedCategory cat = (FeedCategory)list.getItemAtPosition(position);
-
- m_selectedCat = null;
- m_adapter.notifyDataSetChanged();
-
- if (cat != null) {
- if (cat.id < 0) {
- m_activity.onCatSelected(cat, false);
- } else {
- m_activity.onCatSelected(cat);
- }
-
- }
- }
- }
-
- public void setSelectedCategory(FeedCategory cat) {
- m_selectedCat = cat;
-
- if (m_adapter != null) {
- m_adapter.notifyDataSetChanged();
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle out) {
- super.onSaveInstanceState(out);
-
- out.putParcelable("m_selectedCat", m_selectedCat);
- }
-}
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java
index da0af1de..f66758ee 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java
@@ -2,6 +2,7 @@ package org.fox.ttrss;
import android.annotation.SuppressLint;
import android.app.Activity;
+import android.app.Dialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
@@ -14,6 +15,7 @@ import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.TextView;
@@ -29,35 +31,42 @@ import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import com.google.android.material.materialswitch.MaterialSwitch;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
import org.fox.ttrss.types.Feed;
-import org.fox.ttrss.types.FeedCategory;
import java.lang.reflect.Type;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
+import java.util.stream.Collectors;
public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeListener,
LoaderManager.LoaderCallbacks<JsonElement> {
private final String TAG = this.getClass().getSimpleName();
- private SharedPreferences m_prefs;
- private MasterActivity m_activity;
- private FeedCategory m_category;
- private int m_selectedFeedId;
- private SwipeRefreshLayout m_swipeLayout;
+ protected SharedPreferences m_prefs;
+ protected MasterActivity m_activity;
+ protected Feed m_feed;
+ private Feed m_selectedFeed;
+ protected SwipeRefreshLayout m_swipeLayout;
private boolean m_enableParentBtn = false;
- private FeedsAdapter m_adapter;
+ protected FeedsAdapter m_adapter;
private RecyclerView m_list;
private RecyclerView.LayoutManager m_layoutManager;
- public void initialize(@NonNull FeedCategory cat, boolean enableParentBtn) {
- m_category = cat;
+ public void initialize(@NonNull Feed feed, boolean enableParentBtn) {
+ Log.d(TAG, "initialize, feed=" + feed);
+
+ m_feed = feed;
m_enableParentBtn = enableParentBtn;
}
@@ -65,23 +74,21 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
public Loader<JsonElement> onCreateLoader(int id, Bundle args) {
if (m_swipeLayout != null) m_swipeLayout.setRefreshing(true);
- final String sessionId = m_activity.getSessionId();
- final boolean unreadOnly = m_activity.getUnreadOnly() && m_category.id != -1; /* starred */
-
HashMap<String,String> params = new HashMap<>();
params.put("op", "getFeeds");
- params.put("sid", sessionId);
+ params.put("sid", m_activity.getSessionId());
params.put("include_nested", "true");
- params.put("cat_id", String.valueOf(m_category.id));
+ params.put("cat_id", String.valueOf(m_feed.id));
- if (unreadOnly)
+ /* except marked */
+ if (m_activity.getUnreadOnly() && m_feed.id != -1)
params.put("unread_only", "true");
return new ApiLoader(getContext(), params);
}
@Override
- public void onLoadFinished(Loader<JsonElement> loader, JsonElement result) {
+ public void onLoadFinished(@NonNull Loader<JsonElement> loader, JsonElement result) {
if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false);
if (result != null) {
@@ -90,7 +97,7 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
if (content != null) {
Type listType = new TypeToken<List<Feed>>() {}.getType();
- final List<Feed> feedsJson = new Gson().fromJson(content, listType);
+ List<Feed> feedsJson = new Gson().fromJson(content, listType);
List<Feed> feeds = new ArrayList<>();
@@ -130,25 +137,32 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
// m_adapter.sortFeeds(feedsJson);
- feeds.add(new Feed(Feed.TYPE_HEADER));
+ //List<Feed> feedsJsonFiltered = feedsJson.stream().filter(a -> a.id >= -10).collect(Collectors.toList());
+
+ if (m_feed.id == Feed.ALL_ARTICLES)
+ feedsJson = feedsJson.stream().filter(a -> a.id > -10).collect(Collectors.toList());
+
+ sortFeeds(feedsJson, m_feed);
+
+ // feeds.add(new Feed(Feed.TYPE_HEADER));
if (m_enableParentBtn) {
- feeds.add(new Feed(Feed.TYPE_GOBACK));
+ feeds.add(0, new Feed(Feed.TYPE_GOBACK));
- if (m_enableParentBtn && m_category.id >= 0 && !feedsJson.isEmpty()) {
- Feed feed = new Feed(m_category.id, m_category.title, true);
- feed.unread = catUnread;
- feed.always_display_as_feed = true;
- feed.display_title = getString(R.string.feed_all_articles);
+ if (m_feed.id >= 0 && !feedsJson.isEmpty()) {
+ Feed feed = new Feed(m_feed.id, m_feed.title, true);
- feeds.add(0, feed);
+ feed.unread = feedsJson.stream().map(a -> a.unread).reduce(0, Integer::sum);
+ feed.always_open_headlines = true;
+
+ feeds.add(1, feed);
}
}
feeds.addAll(feedsJson);
feeds.add(new Feed(Feed.TYPE_DIVIDER));
- feeds.add(new Feed(Feed.TYPE_TOGGLE_UNREAD));
+ feeds.add(new Feed(Feed.TYPE_TOGGLE_UNREAD, getString(R.string.unread_only), true));
m_adapter.submitList(feeds);
@@ -156,7 +170,7 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
}
} catch (Exception e) {
- e.printStackTrace();
+ m_activity.toast(e.getMessage());
}
}
@@ -212,6 +226,17 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
}
@SuppressLint("DefaultLocale")
+ static class SpecialOrderComparator implements Comparator<Feed> {
+ static List<Integer> order = Arrays.asList(Feed.ALL_ARTICLES, Feed.FRESH, Feed.MARKED,
+ Feed.PUBLISHED, Feed.ARCHIVED, Feed.RECENTLY_READ);
+
+ @Override
+ public int compare(Feed a, Feed b) {
+ return Integer.valueOf(order.indexOf(a.id)).compareTo(order.indexOf(b.id));
+ }
+ }
+
+ @SuppressLint("DefaultLocale")
static class FeedOrderComparator implements Comparator<Feed> {
@Override
@@ -241,46 +266,42 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
@Override
public boolean onContextItemSelected(MenuItem item) {
- /* AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item
.getMenuInfo();
+
+ final Feed feed = m_adapter.getCurrentList().get(info.position);
+
+ Log.d(TAG, "context for feed=" + feed.id);
+
int itemId = item.getItemId();
if (itemId == R.id.browse_headlines) {
- Feed feed = getFeedAtPosition(info.position);
- if (feed != null) {
- m_activity.onFeedSelected(feed);
- }
+ Feed forceFeed = new Feed(feed);
+ forceFeed.always_open_headlines = true;
+
+ m_activity.onFeedSelected(forceFeed);
return true;
} else if (itemId == R.id.browse_feeds) {
- Feed feed = getFeedAtPosition(info.position);
- if (feed != null) {
- m_activity.onCatSelected(new FeedCategory(feed.id, feed.title, feed.unread), false);
- }
+ m_activity.onFeedSelected(feed);
+ //m_activity.onCatSelected(new FeedCategory(feed.id, feed.title, feed.unread), false);
return true;
} else if (itemId == R.id.unsubscribe_feed) {
- final Feed feed = getFeedAtPosition(info.position);
- if (feed != null) {
- MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext())
- .setMessage(getString(R.string.unsubscribe_from_prompt, feed.title))
- .setPositiveButton(R.string.unsubscribe,
- (dialog, which) -> m_activity.unsubscribeFeed(feed))
- .setNegativeButton(R.string.dialog_cancel,
- (dialog, which) -> {
-
- });
-
- Dialog dlg = builder.create();
- dlg.show();
- }
+ MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext())
+ .setMessage(getString(R.string.unsubscribe_from_prompt, feed.title))
+ .setPositiveButton(R.string.unsubscribe,
+ (dialog, which) -> m_activity.unsubscribeFeed(feed))
+ .setNegativeButton(R.string.dialog_cancel,
+ (dialog, which) -> {
+
+ });
+
+ Dialog dlg = builder.create();
+ dlg.show();
return true;
} else if (itemId == R.id.catchup_feed) {
- Feed feed = getFeedAtPosition(info.position);
-
- if (feed != null) {
- m_activity.catchupDialog(feed);
- }
+ m_activity.catchupDialog(feed);
return true;
- } */
+ }
Log.d(TAG, "onContextItemSelected, unhandled id=" + item.getItemId());
return super.onContextItemSelected(item);
@@ -289,14 +310,14 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
+
+ m_activity.getMenuInflater().inflate(R.menu.context_feed, menu);
- /* getActivity().getMenuInflater().inflate(R.menu.context_feed, menu);
-
- AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- Feed feed = (Feed) m_list.getItemAtPosition(info.position);
+ Feed feed = m_adapter.getCurrentList().get(info.position);
- menu.setHeaderTitle(feed.display_title != null ? feed.display_title : feed.title);
+ menu.setHeaderTitle(feed.title);
if (!feed.is_cat) {
menu.findItem(R.id.browse_feeds).setVisible(false);
@@ -304,7 +325,7 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
if (feed.id <= 0) {
menu.findItem(R.id.unsubscribe_feed).setVisible(false);
- } */
+ }
super.onCreateContextMenu(menu, v, menuInfo);
@@ -315,8 +336,8 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
- m_catId = savedInstanceState.getInt("m_catId");
- m_selectedFeedId = savedInstanceState.getInt("m_selectedId");
+ m_feed = savedInstanceState.getParcelable("m_feed");
+ m_selectedFeed = savedInstanceState.getParcelable("m_selectedFeed");
m_enableParentBtn = savedInstanceState.getBoolean("m_enableParentBtn");
}
}
@@ -325,15 +346,15 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
public void onSaveInstanceState(Bundle out) {
super.onSaveInstanceState(out);
- out.putInt("m_catId", m_catId);
- out.putInt("m_selectedId", m_selectedFeedId);
+ out.putParcelable("m_feed", m_feed);
+ out.putParcelable("m_selectedFeed", m_selectedFeed);
out.putBoolean("m_enableParentBtn", m_enableParentBtn);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.fragment_feeds_recycler, container, false);
+ View view = inflater.inflate(R.layout.fragment_feeds, container, false);
m_swipeLayout = view.findViewById(R.id.feeds_swipe_container);
@@ -349,19 +370,32 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
m_adapter = new FeedsAdapter();
m_list.setAdapter(m_adapter);
- /* if (m_enableParentBtn) {
- View layout = inflater.inflate(R.layout.feeds_goback, m_list, false);
+ TextView login = view.findViewById(R.id.drawer_header_login);
- layout.setOnClickListener(view1 -> m_activity.getSupportFragmentManager().popBackStack());
+ if (login != null) {
+ login.setText(m_prefs.getString("login", ""));
+ }
- m_list.addHeaderView(layout, null, false);
+ TextView server = view.findViewById(R.id.drawer_header_server);
+
+ if (server != null) {
+ try {
+ server.setText(new URL(m_prefs.getString("ttrss_url", "")).getHost());
+ } catch (MalformedURLException e) {
+ server.setText("");
+ }
}
- m_adapter = new FeedListAdapter(getActivity(), R.layout.feeds_row, m_feeds);
- m_list.setAdapter(m_adapter);
- m_list.setOnItemClickListener(this);
+ View settingsBtn = view.findViewById(R.id.drawer_settings_btn);
- registerForContextMenu(m_list); */
+ if (settingsBtn != null) {
+ settingsBtn.setOnClickListener(v -> {
+ Intent intent = new Intent(getActivity(),
+ PreferencesActivity.class);
+
+ startActivityForResult(intent, 0);
+ });
+ }
return view;
}
@@ -385,38 +419,17 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
public void onResume() {
super.onResume();
- LoaderManager.getInstance(this).initLoader(Application.LOADER_FEEDS, null, this).forceLoad();
+ Log.d(TAG, "onResume");
+
+ refresh();
m_activity.invalidateOptionsMenu();
}
-
- /* @Override
- public void onItemClick(AdapterView<?> av, View view, int position, long id) {
- ListView list = (ListView)av;
-
- if (list != null) {
- Feed feed = (Feed)list.getItemAtPosition(position);
-
- if (feed != null) {
- if (feed.is_cat) {
- if (feed.always_display_as_feed) {
- m_activity.onCatSelected(new FeedCategory(feed.id, feed.title, feed.unread), true);
- } else if (feed.id < 0) {
- m_activity.onCatSelected(new FeedCategory(feed.id, feed.title, feed.unread), false);
- } else {
- m_activity.onCatSelected(new FeedCategory(feed.id, feed.title, feed.unread));
- }
- } else {
- m_activity.onFeedSelected(feed);
- }
- }
-
- //m_selectedFeed = feed;
- //m_adapter.notifyDataSetChanged();
- }
- } */
public void refresh() {
+ if (!isAdded())
+ return;
+
if (m_swipeLayout != null) {
m_swipeLayout.setRefreshing(true);
}
@@ -430,10 +443,7 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
private ImageView icon;
private TextView title;
private TextView unreadCounter;
- private TextView rowSwitch;
- private View settingsBtn;
- private TextView login;
- private TextView server;
+ private MaterialSwitch rowSwitch;
public FeedViewHolder(@NonNull View itemView) {
super(itemView);
@@ -443,9 +453,6 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
title = itemView.findViewById(R.id.title);
unreadCounter = itemView.findViewById(R.id.unread_counter);
rowSwitch = itemView.findViewById(R.id.row_switch);
- settingsBtn = itemView.findViewById(R.id.drawer_settings_btn);
- login = itemView.findViewById(R.id.drawer_header_login);
- server = itemView.findViewById(R.id.drawer_header_server);
}
}
@@ -465,11 +472,10 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
}
}
- private class FeedsAdapter extends ListAdapter<Feed, FeedViewHolder> {
+ protected class FeedsAdapter extends ListAdapter<Feed, FeedViewHolder> {
public static final int VIEW_NORMAL = 0;
public static final int VIEW_SELECTED = 1;
public static final int VIEW_GOBACK = 2;
- public static final int VIEW_HEADER = 3;
public static final int VIEW_TOGGLE_UNREAD = 4;
public static final int VIEW_DIVIDER = 5;
@@ -492,9 +498,6 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
case VIEW_TOGGLE_UNREAD:
layoutId = R.layout.feeds_row_toggle;
break;
- case VIEW_HEADER:
- layoutId = R.layout.feeds_row_header;
- break;
case VIEW_DIVIDER:
layoutId = R.layout.feeds_row_divider;
break;
@@ -508,31 +511,13 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
Feed feed = getItem(position);
if (holder.icon != null) {
- if (feed.id == Feed.TYPE_GOBACK) {
- holder.icon.setImageResource(R.drawable.baseline_arrow_back_24);
- } else if (feed.id == 0 && !feed.is_cat) {
- holder.icon.setImageResource(R.drawable.baseline_archive_24);
- } else if (feed.id == -1 && !feed.is_cat) {
- holder.icon.setImageResource(R.drawable.baseline_star_24);
- } else if (feed.id == -2 && !feed.is_cat) {
- holder.icon.setImageResource(R.drawable.rss);
- } else if (feed.id == -3 && !feed.is_cat) {
- holder.icon.setImageResource(R.drawable.baseline_local_fire_department_24);
- } else if (feed.id == -4 && !feed.is_cat) {
- holder.icon.setImageResource(R.drawable.baseline_inbox_24);
- } else if (feed.id == -6 && !feed.is_cat) {
- holder.icon.setImageResource(R.drawable.baseline_restore_24);
- } else if (feed.is_cat) {
- holder.icon.setImageResource(R.drawable.baseline_folder_open_24);
- } else {
- holder.icon.setImageResource(R.drawable.rss);
- }
+ holder.icon.setImageResource(getIconForFeed(feed));
}
if (holder.title != null) {
- holder.title.setText(feed.display_title != null ? feed.display_title : feed.title);
+ holder.title.setText(feed.title);
- if (feed.always_display_as_feed || (!feed.is_cat && feed.id == -4)) {
+ if (feed.always_open_headlines || (!feed.is_cat && feed.id == -4)) {
holder.title.setTypeface(null, Typeface.BOLD);
} else {
holder.title.setTypeface(null, Typeface.NORMAL);
@@ -545,26 +530,43 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
holder.unreadCounter.setVisibility((feed.unread > 0) ? View.VISIBLE : View.INVISIBLE);
}
- if (holder.settingsBtn != null) {
- holder.settingsBtn.setOnClickListener(view -> {
- Intent intent = new Intent(getActivity(),
- PreferencesActivity.class);
+ // there's only one kind of row with checkbox atm
+ if (holder.rowSwitch != null) {
+ holder.rowSwitch.setChecked(m_activity.getUnreadOnly());
- startActivityForResult(intent, 0);
+ holder.rowSwitch.setOnCheckedChangeListener((button, isChecked) -> {
+ m_activity.setUnreadOnly(isChecked);
+ refresh();
});
}
+ holder.view.setOnLongClickListener(view -> {
+ if (feed.id != Feed.TYPE_TOGGLE_UNREAD && feed.id != Feed.TYPE_DIVIDER && feed.id != Feed.TYPE_GOBACK && feed.id != Feed.ALL_ARTICLES) {
+ m_list.showContextMenuForChild(view);
+ }
+ return true;
+ });
+
holder.view.setOnClickListener(view -> {
- if (feed.is_cat) {
+ if (feed.id == Feed.TYPE_GOBACK) {
+ m_activity.getSupportFragmentManager().popBackStack();
+ } else if (feed.id == Feed.TYPE_TOGGLE_UNREAD || feed.id == Feed.TYPE_DIVIDER) {
+ //
+ } else {
+
+ /* if (feed.is_cat) {
if (feed.always_display_as_feed) {
- m_activity.onCatSelected(new FeedCategory(feed.id, feed.title, feed.unread), true);
+ //m_activity.onCatSelected(new FeedCategory(feed.id, feed.title, feed.unread), true);
} else if (feed.id < 0) {
- m_activity.onCatSelected(new FeedCategory(feed.id, feed.title, feed.unread), false);
+ //m_activity.onCatSelected(new FeedCategory(feed.id, feed.title, feed.unread), false);
} else {
- m_activity.onCatSelected(new FeedCategory(feed.id, feed.title, feed.unread));
+ //m_activity.onCatSelected(new FeedCategory(feed.id, feed.title, feed.unread));
}
} else {
m_activity.onFeedSelected(feed);
+ } */
+
+ m_activity.onFeedSelected(feed);
}
});
}
@@ -577,20 +579,22 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
return VIEW_GOBACK;
} else if (feed.id == Feed.TYPE_DIVIDER) {
return VIEW_DIVIDER;
- } else if (feed.id == Feed.TYPE_HEADER) {
- return VIEW_HEADER;
} else if (feed.id == Feed.TYPE_TOGGLE_UNREAD) {
return VIEW_TOGGLE_UNREAD;
- } else if (feed.id == m_selectedFeedId) {
+ } else if (m_selectedFeed != null && feed.id == m_selectedFeed.id && feed.is_cat && m_selectedFeed.is_cat) {
return VIEW_SELECTED;
} else {
return VIEW_NORMAL;
}
}
+ }
- public void sortFeeds(List<Feed> feeds) {
- Comparator<Feed> cmp;
+ protected void sortFeeds(List<Feed> feeds, Feed feed) {
+ Comparator<Feed> cmp;
+ if (feed.id == -1) {
+ cmp = new SpecialOrderComparator();
+ } else {
if (m_prefs.getBoolean("sort_feeds_by_unread", false)) {
cmp = new FeedUnreadComparator();
} else {
@@ -600,36 +604,54 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL
cmp = new FeedTitleComparator();
}
}
+ }
- try {
- feeds.sort(cmp);
- } catch (IllegalArgumentException e) {
- // sort order got changed in prefs or something
- e.printStackTrace();
- }
+ try {
+ feeds.sort(cmp);
+ } catch (IllegalArgumentException e) {
+ //
}
}
+ protected int getIconForFeed(Feed feed) {
+ if (feed.id == Feed.TYPE_GOBACK) {
+ return R.drawable.baseline_arrow_back_24;
+ } else if (feed.id == Feed.TYPE_TOGGLE_UNREAD) {
+ return R.drawable.baseline_filter_alt_24;
+ } else if (feed.id == 0 && !feed.is_cat) {
+ return R.drawable.baseline_archive_24;
+ } else if (feed.id == -1 && !feed.is_cat) {
+ return R.drawable.baseline_star_24;
+ } else if (feed.id == -2 && !feed.is_cat) {
+ return R.drawable.rss;
+ } else if (feed.id == -3 && !feed.is_cat) {
+ return R.drawable.baseline_local_fire_department_24;
+ } else if (feed.id == -4 && !feed.is_cat) {
+ return R.drawable.baseline_inbox_24;
+ } else if (feed.id == -6 && !feed.is_cat) {
+ return R.drawable.baseline_restore_24;
+ } else if (feed.is_cat) {
+ return R.drawable.baseline_folder_open_24;
+ } else if (feed.id < -10 && !feed.is_cat) {
+ return R.drawable.baseline_label_24;
+ } else {
+ return R.drawable.rss;
+ }
+ }
+
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
- refresh();
+ // Can't access ViewModels from detached fragment (= backstack)
+ if (isAdded())
+ refresh();
}
- /* public Feed getFeedAtPosition(int position) {
- try {
- return (Feed) m_list.getItemAtPosition(position);
- } catch (ArrayIndexOutOfBoundsException e) {
- e.printStackTrace();
- }
-
- return null;
- } */
- public void setSelectedFeedId(int feedId) {
+ public void setSelectedFeed(Feed feed) {
if (m_adapter != null) {
- m_selectedFeedId = feedId;
+ m_selectedFeed = feed;
// TODO handle properly
m_adapter.notifyDataSetChanged();
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 9757f090..77ef1f8b 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
@@ -34,6 +34,7 @@ import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.CheckBox;
import android.widget.EditText;
@@ -134,7 +135,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
public void initialize(Feed feed, int activeArticleId, boolean compactMode) {
m_feed = feed;
- m_compactLayoutMode = compactMode;
+ m_compactLayoutMode = compactMode;
m_activeArticleId = activeArticleId;
}
@@ -245,6 +246,12 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
getActivity().getMenuInflater().inflate(R.menu.context_headlines, menu);
+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
+
+ Article article = m_adapter.getCurrentList().get(info.position);
+
+ menu.setHeaderTitle(article.title);
+
menu.findItem(R.id.article_set_labels).setEnabled(m_activity.getApiLevel() >= 1);
menu.findItem(R.id.article_edit_note).setEnabled(m_activity.getApiLevel() >= 1);
@@ -454,10 +461,6 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
}
});
- if (m_activity.isSmallScreen() && m_feed != null) {
- m_activity.setTitle(m_feed.title);
- }
-
ArticleModel model = Application.getArticlesModel();
// this gets notified on network update
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/MasterActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/MasterActivity.java
index 11265769..c92123dd 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/MasterActivity.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/MasterActivity.java
@@ -7,7 +7,6 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
@@ -28,9 +27,7 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.gson.JsonElement;
import org.fox.ttrss.types.Article;
-import org.fox.ttrss.types.ArticleList;
import org.fox.ttrss.types.Feed;
-import org.fox.ttrss.types.FeedCategory;
import java.util.Date;
import java.util.HashMap;
@@ -46,7 +43,6 @@ public class MasterActivity extends OnlineActivity implements HeadlinesEventList
protected long m_lastWidgetRefresh = 0;
protected boolean m_feedIsSelected = false;
- protected boolean m_userFeedSelected = false;
private ActionBarDrawerToggle m_drawerToggle;
private DrawerLayout m_drawerLayout;
@@ -139,11 +135,11 @@ public class MasterActivity extends OnlineActivity implements HeadlinesEventList
// app shortcuts are not allowed to pass string extras
if (feedTitle == null)
- feedTitle = Feed.getSpecialFeedTitleById(MasterActivity.this, feedId);
+ feedTitle = getString(Feed.getSpecialFeedTitleId(feedId, isCat));
Feed tmpFeed = new Feed(feedId, feedTitle, isCat);
- onFeedSelected(tmpFeed, false);
+ onFeedSelected(tmpFeed);
}
@Override
@@ -159,21 +155,13 @@ public class MasterActivity extends OnlineActivity implements HeadlinesEventList
lr.execute(map);
}
-
- //m_pullToRefreshAttacher.setRefreshing(true);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+ RootCategoriesFragment fc = new RootCategoriesFragment();
- /* if (m_prefs.getBoolean("enable_cats", true)) {
- ft.replace(R.id.feeds_fragment, new FeedCategoriesFragment(), FRAG_CATS);
- } else {
- ft.replace(R.id.feeds_fragment, new FeedsFragment(), FRAG_FEEDS);
- } */
-
- FeedsFragment ff = new FeedsFragment();
- ff.initialize(-4, false);
-
- ft.replace(R.id.feeds_fragment, ff, FRAG_FEEDS);
+ // it doesn't matter which feed is used here
+ fc.initialize(new Feed(-1, getString(R.string.cat_special), true), false);
+ ft.replace(R.id.feeds_fragment, fc, FRAG_FEEDS);
// allow overriding feed to open on startup in non-shortcut mode, default to
// open_on_startup prefs setting and not-category
@@ -185,12 +173,12 @@ public class MasterActivity extends OnlineActivity implements HeadlinesEventList
String openFeedTitle = i.getStringExtra("feed_title");
if (openFeedTitle == null)
- openFeedTitle = Feed.getSpecialFeedTitleById(this, openFeedId);
+ openFeedTitle = getString(Feed.getSpecialFeedTitleId(openFeedId, openFeedIsCat));
if (!shortcutMode && openFeedId != 0) {
Log.d(TAG, "opening feed id: " + openFeedId);
- onFeedSelected(new Feed(openFeedId, openFeedTitle, openFeedIsCat), false);
+ onFeedSelected(new Feed(openFeedId, openFeedTitle, openFeedIsCat));
} else if (m_drawerLayout != null) {
m_drawerLayout.openDrawer(GravityCompat.START);
}
@@ -202,7 +190,6 @@ public class MasterActivity extends OnlineActivity implements HeadlinesEventList
} else { // savedInstanceState != null
m_feedIsSelected = savedInstanceState.getBoolean("m_feedIsSelected");
- m_userFeedSelected = savedInstanceState.getBoolean("m_userFeedSelected");
if (m_drawerLayout != null && !m_feedIsSelected) {
m_drawerLayout.openDrawer(GravityCompat.START);
@@ -261,91 +248,96 @@ public class MasterActivity extends OnlineActivity implements HeadlinesEventList
if (m_menu != null && getSessionId() != null) {
Fragment ff = getSupportFragmentManager().findFragmentByTag(FRAG_FEEDS);
- Fragment cf = getSupportFragmentManager().findFragmentByTag(FRAG_CATS);
HeadlinesFragment hf = (HeadlinesFragment)getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES);
- m_menu.setGroupVisible(R.id.menu_group_feeds, (ff != null && ff.isAdded()) || (cf != null && cf.isAdded()));
+ m_menu.setGroupVisible(R.id.menu_group_feeds, ff != null && ff.isAdded());
m_menu.setGroupVisible(R.id.menu_group_headlines, hf != null && hf.isAdded());
}
}
- public void onFeedSelected(Feed feed) {
- onFeedSelected(feed, true);
- }
-
- public void onFeedSelected(final Feed feed, final boolean selectedByUser) {
+ public void onFeedSelected(Feed feed) {
- FeedsFragment ff = (FeedsFragment) getSupportFragmentManager().findFragmentByTag(FRAG_FEEDS);
+ if (isSmallScreen())
+ setTitle(feed.title);
- if (ff != null && ff.isAdded()) {
- ff.setSelectedFeedId(feed.id);
- }
+ if (feed.is_cat && !feed.always_open_headlines) {
+ FragmentTransaction ft = getSupportFragmentManager()
+ .beginTransaction();
- if (m_drawerLayout != null) {
- m_drawerLayout.closeDrawers();
- }
+ FeedsFragment ff = new FeedsFragment();
+ ff.initialize(feed, true);
+ ft.replace(R.id.feeds_fragment, ff, FRAG_FEEDS);
- Application.getArticles().clear();
+ ft.addToBackStack(null);
+ ft.commit();
- new Handler().postDelayed(() -> {
- FragmentTransaction ft = getSupportFragmentManager()
- .beginTransaction();
+ } else {
+ FeedsFragment ff = (FeedsFragment) getSupportFragmentManager().findFragmentByTag(FRAG_FEEDS);
- HeadlinesFragment hf = new HeadlinesFragment();
- hf.initialize(feed);
+ if (ff != null) {
+ ff.setSelectedFeed(feed);
+ }
- ft.replace(R.id.headlines_fragment, hf, FRAG_HEADLINES);
+ if (m_drawerLayout != null) {
+ m_drawerLayout.closeDrawers();
+ }
- ft.commit();
+ HeadlinesFragment hf = (HeadlinesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_HEADLINES);
- m_feedIsSelected = true;
- m_userFeedSelected = selectedByUser;
+ if (hf != null) {
+ hf.initialize(feed);
+ hf.refresh(false);
+ } else {
+ FragmentTransaction ft = getSupportFragmentManager()
+ .beginTransaction();
- }, 250);
+ hf = new HeadlinesFragment();
+ hf.initialize(feed);
- Date date = new Date();
+ ft.replace(R.id.headlines_fragment, hf, FRAG_HEADLINES);
- if (date.getTime() - m_lastRefresh > 30*1000) {
- m_lastRefresh = date.getTime();
- refresh(false);
- }
- }
-
- public void onCatSelected(FeedCategory cat, boolean openAsFeed) {
- FeedCategoriesFragment fc = (FeedCategoriesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_CATS);
-
- //m_pullToRefreshAttacher.setRefreshing(true);
-
- if (!openAsFeed) {
-
- if (fc != null && fc.isAdded()) {
- fc.setSelectedCategory(null);
+ ft.commit();
}
- FragmentTransaction ft = getSupportFragmentManager()
+ /* FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
- FeedsFragment ff = new FeedsFragment();
- ff.initialize(cat.id, true);
- ft.replace(R.id.feeds_fragment, ff, FRAG_FEEDS);
+ HeadlinesFragment hf = new HeadlinesFragment();
+ hf.initialize(feed);
+ hf.refresh(false);
+
+ ft.replace(R.id.headlines_fragment, hf, FRAG_HEADLINES);
- ft.addToBackStack(null);
ft.commit();
- } else {
-
- if (fc != null) {
- fc.setSelectedCategory(cat);
- }
+ m_feedIsSelected = true;
- Feed feed = new Feed(cat.id, cat.title, true);
- onFeedSelected(feed);
+ Date date = new Date();
+
+ if (date.getTime() - m_lastRefresh > 30 * 1000) {
+ m_lastRefresh = date.getTime();
+ refresh(false);
+ } */
}
}
- public void onCatSelected(FeedCategory cat) {
- onCatSelected(cat, m_prefs.getBoolean("browse_cats_like_feeds", false));
- }
+ /* public void onCatSelected(Feed cat) {
+ FeedCategoriesFragment fc = (FeedCategoriesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_CATS);
+
+ if (fc != null) {
+ fc.setSelectedCategory(null);
+ }
+
+ FragmentTransaction ft = getSupportFragmentManager()
+ .beginTransaction();
+
+ FeedsFragment ff = new FeedsFragment();
+ ff.initialize(, true);
+ ft.replace(R.id.feeds_fragment, ff, FRAG_FEEDS);
+
+ ft.addToBackStack(null);
+ ft.commit();
+ } */
@Override
public void logout() {
@@ -412,7 +404,7 @@ public class MasterActivity extends OnlineActivity implements HeadlinesEventList
@Override
public void onBackPressed() {
if (m_drawerLayout != null && !m_drawerLayout.isDrawerOpen(GravityCompat.START) &&
- (getSupportFragmentManager().getBackStackEntryCount() > 0 || m_userFeedSelected)) {
+ (getSupportFragmentManager().getBackStackEntryCount() > 0)) {
m_drawerLayout.openDrawer(GravityCompat.START);
} else {
@@ -437,7 +429,6 @@ public class MasterActivity extends OnlineActivity implements HeadlinesEventList
super.onSaveInstanceState(out);
out.putBoolean("m_feedIsSelected", m_feedIsSelected);
- out.putBoolean("m_userFeedSelected", m_userFeedSelected);
Application.getInstance().save(out);
}
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 ffca776b..c946f405 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
@@ -8,7 +8,6 @@ import android.content.SharedPreferences;
import android.content.res.ColorStateList;
import android.graphics.Point;
import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -1231,12 +1230,6 @@ article.score = Integer.parseInt(edit.getText().toString());
}
protected void refresh(boolean includeHeadlines) {
- FeedCategoriesFragment cf = (FeedCategoriesFragment) getSupportFragmentManager().findFragmentByTag(FRAG_CATS);
-
- if (cf != null) {
- cf.refresh();
- }
-
FeedsFragment ff = (FeedsFragment) getSupportFragmentManager().findFragmentByTag(FRAG_FEEDS);
if (ff != null) {
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/RootCategoriesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/RootCategoriesFragment.java
new file mode 100755
index 00000000..cb91cc14
--- /dev/null
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/RootCategoriesFragment.java
@@ -0,0 +1,134 @@
+package org.fox.ttrss;
+
+import android.annotation.SuppressLint;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.loader.content.Loader;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.reflect.TypeToken;
+
+import org.fox.ttrss.types.Feed;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class RootCategoriesFragment extends FeedsFragment {
+ private final String TAG = this.getClass().getSimpleName();
+
+ @Override
+ @NonNull
+ public Loader<JsonElement> onCreateLoader(int id, Bundle args) {
+ HashMap<String, String> params = new HashMap<>();
+ params.put("op", "getCategories");
+ params.put("sid", m_activity.getSessionId());
+
+ // this confusingly named option means "return top level categories only"
+ params.put("enable_nested", "true");
+
+ if (m_activity.getUnreadOnly())
+ params.put("unread_only", "true");
+
+ return new ApiLoader(getContext(), params);
+ }
+
+ @SuppressLint("DefaultLocale")
+ static class CatOrderComparator implements Comparator<Feed> {
+
+ @Override
+ public int compare(Feed a, Feed b) {
+ if (a.id >= 0 && b.id >= 0)
+ if (a.order_id != 0 && b.order_id != 0)
+ return a.order_id - b.order_id;
+ else
+ return a.title.toUpperCase().compareTo(b.title.toUpperCase());
+ else
+ return a.id - b.id;
+ }
+
+ }
+
+ @Override
+ protected void sortFeeds(List<Feed> feeds, Feed feed) {
+ try {
+ feeds.sort(new CatOrderComparator());
+ } catch (IllegalArgumentException e) {
+ //
+ }
+ }
+
+ @Override
+ protected int getIconForFeed(Feed feed) {
+ if (feed.id == Feed.TYPE_TOGGLE_UNREAD)
+ return super.getIconForFeed(feed);
+ else
+ return R.drawable.baseline_folder_open_24;
+ }
+
+ @Override
+ public void onLoadFinished(Loader<JsonElement> loader, JsonElement result) {
+ if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false);
+
+ if (result != null) {
+ try {
+ JsonArray content = result.getAsJsonArray();
+ if (content != null) {
+
+ Type listType = new TypeToken<List<Feed>>() {}.getType();
+ List<Feed> feedsJson = new Gson().fromJson(content, listType);
+
+ List<Feed> feeds = new ArrayList<>();
+
+ sortFeeds(feedsJson, m_feed);
+
+ // virtual cats implemented in getCategories since api level 1
+ if (m_activity.getApiLevel() == 0) {
+ feeds.add(0, new Feed(-2, getString(R.string.cat_labels), false));
+ feeds.add(1, new Feed(-1, getString(R.string.cat_special), false));
+ feeds.add(new Feed(0, getString(R.string.cat_uncategorized), false));
+ }
+
+ if (feedsJson.stream().noneMatch(a -> a.id == -1))
+ feeds.add(new Feed(-1, getString(R.string.cat_special), true));
+
+ for (Feed f : feedsJson) {
+ f.is_cat = true;
+ feeds.add(f);
+ }
+
+ feeds.add(new Feed(Feed.TYPE_DIVIDER));
+ feeds.add(new Feed(Feed.TYPE_TOGGLE_UNREAD, getString(R.string.unread_only), true));
+
+ m_adapter.submitList(feeds);
+
+ return;
+ }
+
+ } catch (Exception e) {
+ m_activity.toast(e.getMessage());
+ }
+ }
+
+ ApiLoader apiLoader = (ApiLoader) loader;
+
+ if (apiLoader.getLastError() != null && apiLoader.getLastError() != ApiCommon.ApiError.SUCCESS) {
+ if (apiLoader.getLastError() == ApiCommon.ApiError.LOGIN_FAILED) {
+ m_activity.login(true);
+ } else {
+ if (apiLoader.getLastErrorMessage() != null) {
+ m_activity.toast(getString(apiLoader.getErrorMessage()) + "\n" + apiLoader.getLastErrorMessage());
+ } else {
+ m_activity.toast(apiLoader.getErrorMessage());
+ }
+ }
+ }
+ }
+}
+
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/types/Feed.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/types/Feed.java
index 5432bad1..f8a2be8f 100644
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/types/Feed.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/types/Feed.java
@@ -1,13 +1,11 @@
package org.fox.ttrss.types;
-import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import org.fox.ttrss.R;
public class Feed implements Comparable<Feed>, Parcelable {
- public static final int TYPE_HEADER = -10000;
public static final int TYPE_GOBACK = -10001;
public static final int TYPE_DIVIDER = -10002;
public static final int TYPE_TOGGLE_UNREAD = -10003;
@@ -21,8 +19,7 @@ public class Feed implements Comparable<Feed>, Parcelable {
public int last_updated;
public int order_id;
public boolean is_cat;
- public boolean always_display_as_feed;
- public String display_title;
+ transient public boolean always_open_headlines;
public Feed(int id) {
this.id = id;
@@ -36,24 +33,61 @@ public class Feed implements Comparable<Feed>, Parcelable {
this.is_cat = is_cat;
}
- // TODO: maybe add special categories? (, bool isCat)
- public static String getSpecialFeedTitleById(Context context, int feedId) {
- switch (feedId) {
- case -1:
- return context.getString(R.string.feed_starred_articles);
- case -2:
- return context.getString(R.string.feed_published_articles);
- case -3:
- return context.getString(R.string.fresh_articles);
- case -4:
- return context.getString(R.string.feed_all_articles);
- case -6:
- return context.getString(R.string.feed_recently_read);
- case 0:
- return context.getString(R.string.feed_archived_articles);
- default:
- return null;
- }
+ public Feed(Feed feed) {
+ id = feed.id;
+ feed_url = feed.feed_url;
+ title = feed.title;
+ unread = feed.unread;
+ has_icon = feed.has_icon;
+ cat_id = feed.cat_id;
+ last_updated = feed.last_updated;
+ order_id = feed.order_id;
+ is_cat = feed.is_cat;
+ always_open_headlines = feed.always_open_headlines;
+ }
+
+ public static final int MARKED = -1;
+ public static final int PUBLISHED = -2;
+ public static final int FRESH = -3;
+ public static final int ALL_ARTICLES = -4;
+ public static final int RECENTLY_READ = -6;
+ public static final int ARCHIVED = 0;
+
+ public static final int CAT_SPECIAL = -1;
+ public static final int CAT_LABELS = -2;
+ public static final int CAT_UNCATEGORIZED = 0;
+
+ public static int getSpecialFeedTitleId(int feedId, boolean isCat) {
+ if (!isCat)
+ switch (feedId) {
+ case MARKED:
+ return R.string.feed_starred_articles;
+ case PUBLISHED:
+ return R.string.feed_published_articles;
+ case FRESH:
+ return R.string.fresh_articles;
+ case ALL_ARTICLES:
+ return R.string.feed_all_articles;
+ case RECENTLY_READ:
+ return R.string.feed_recently_read;
+ case ARCHIVED:
+ return R.string.feed_archived_articles;
+ case TYPE_TOGGLE_UNREAD:
+ return R.string.unread_only;
+ default:
+ throw new IllegalArgumentException("Invalid special feed id: " + feedId);
+ }
+ else
+ switch (feedId) {
+ case CAT_LABELS:
+ return R.string.cat_labels;
+ case CAT_SPECIAL:
+ return R.string.cat_special;
+ case CAT_UNCATEGORIZED:
+ return R.string.cat_uncategorized;
+ default:
+ throw new IllegalArgumentException("Invalid special category id: " + feedId);
+ }
}
public Feed(Parcel in) {
@@ -98,8 +132,7 @@ public class Feed implements Comparable<Feed>, Parcelable {
out.writeInt(last_updated);
out.writeInt(is_cat ? 1 : 0);
out.writeInt(order_id);
- out.writeInt(always_display_as_feed ? 1 : 0);
- out.writeString(display_title);
+ out.writeInt(always_open_headlines ? 1 : 0);
}
public void readFromParcel(Parcel in) {
@@ -112,8 +145,7 @@ public class Feed implements Comparable<Feed>, Parcelable {
last_updated = in.readInt();
is_cat = in.readInt() == 1;
order_id = in.readInt();
- always_display_as_feed = in.readInt() == 1;
- display_title = in.readString();
+ always_open_headlines = in.readInt() == 1;
}
@SuppressWarnings("rawtypes")
diff --git a/org.fox.ttrss/src/main/res/drawable/baseline_label_24.xml b/org.fox.ttrss/src/main/res/drawable/baseline_label_24.xml
new file mode 100644
index 00000000..02371e76
--- /dev/null
+++ b/org.fox.ttrss/src/main/res/drawable/baseline_label_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="M17.63,5.84C17.27,5.33 16.67,5 16,5L5,5.01C3.9,5.01 3,5.9 3,7v10c0,1.1 0.9,1.99 2,1.99L16,19c0.67,0 1.27,-0.33 1.63,-0.84L22,12l-4.37,-6.16z"/>
+
+</vector>
diff --git a/org.fox.ttrss/src/main/res/layout/feeds_row_header.xml b/org.fox.ttrss/src/main/res/layout/feeds_row_header.xml
deleted file mode 100755
index f4954259..00000000
--- a/org.fox.ttrss/src/main/res/layout/feeds_row_header.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="72dp"
- xmlns:tools="http://schemas.android.com/tools"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:orientation="vertical"
- android:weightSum="1"
- android:clickable="false">
-
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <com.google.android.material.button.MaterialButton
- style="?attr/materialIconButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scaleX="1.5"
- android:scaleY="1.5"
- app:icon="@drawable/baseline_settings_24"
- android:id="@+id/drawer_settings_btn"
- android:layout_gravity="center_vertical|end"
- android:layout_marginEnd="8dp"
- android:transitionName="SETTINGS_REVEAL"
- />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_alignParentBottom="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:id="@+id/linearLayout"
- android:layout_gravity="center_horizontal|bottom">
-
- <TextView
- android:id="@+id/drawer_header_login"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- tools:text="user"
- android:textAppearance="?attr/textAppearanceHeadlineSmall"
- android:textColor="?attr/colorOnSurface"/>
-
- <TextView
- android:id="@+id/drawer_header_server"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp"
- tools:text="example.org"
- android:textAppearance="?attr/textAppearanceTitleSmall"
- android:textColor="?attr/colorOnSurfaceVariant"/>
- </LinearLayout>
- </FrameLayout>
-
- <ProgressBar
- style="?android:attr/progressBarStyleHorizontal"
- android:visibility="invisible"
- android:indeterminate="true"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:id="@+id/feeds_loading_bar"
- android:layout_alignParentLeft="true"
- android:layout_alignParentBottom="true"
- android:layout_gravity="bottom" />
-</FrameLayout> \ No newline at end of file
diff --git a/org.fox.ttrss/src/main/res/layout/fragment_feeds.xml b/org.fox.ttrss/src/main/res/layout/fragment_feeds.xml
index bf26e3fc..9f57dda2 100755
--- a/org.fox.ttrss/src/main/res/layout/fragment_feeds.xml
+++ b/org.fox.ttrss/src/main/res/layout/fragment_feeds.xml
@@ -1,24 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+ 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/feeds_fragment"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
- <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
- android:id="@+id/feeds_swipe_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <ListView
- android:id="@+id/feeds"
- android:dividerHeight="4dp"
- android:divider="@null"
- android:paddingStart="4dp"
- android:paddingEnd="4dp"
+ <com.google.android.material.appbar.AppBarLayout
+ android:background="@null"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <FrameLayout
+ app:layout_scrollFlags="scroll|enterAlways"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true">
- </ListView>
+ android:layout_height="wrap_content">
+
+ <com.google.android.material.button.MaterialButton
+ style="?attr/materialIconButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleX="1.5"
+ android:scaleY="1.5"
+ app:icon="@drawable/baseline_settings_24"
+ android:id="@+id/drawer_settings_btn"
+ android:layout_gravity="center_vertical|end"
+ android:layout_marginEnd="8dp"
+ android:transitionName="SETTINGS_REVEAL"
+ />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:id="@+id/linearLayout"
+ android:layout_gravity="center_horizontal|bottom">
+
+ <TextView
+ android:id="@+id/drawer_header_login"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ tools:text="user"
+ android:textAppearance="?attr/textAppearanceHeadlineSmall"
+ android:textColor="?attr/colorOnSurface"/>
+
+ <TextView
+ android:id="@+id/drawer_header_server"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ tools:text="example.org"
+ android:textAppearance="?attr/textAppearanceTitleSmall"
+ android:textColor="?attr/colorOnSurfaceVariant"/>
+ </LinearLayout>
+ </FrameLayout>
+
+ </com.google.android.material.appbar.AppBarLayout>
+
+ <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+ android:id="@+id/feeds_swipe_container"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <org.fox.ttrss.util.ContextMenuRecyclerView
+ android:id="@+id/feeds"
+ android:scrollbars="vertical"
+
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
-</RelativeLayout> \ No newline at end of file
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/org.fox.ttrss/src/main/res/layout/fragment_feeds_recycler.xml b/org.fox.ttrss/src/main/res/layout/fragment_feeds_recycler.xml
deleted file mode 100755
index 1ed85a5b..00000000
--- a/org.fox.ttrss/src/main/res/layout/fragment_feeds_recycler.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/feeds_fragment"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
-
- <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
- android:id="@+id/feeds_swipe_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <org.fox.ttrss.util.ContextMenuRecyclerView
- android:id="@+id/feeds"
- android:scrollbars="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
-</RelativeLayout> \ No newline at end of file
diff --git a/org.fox.ttrss/src/main/res/xml/preferences.xml b/org.fox.ttrss/src/main/res/xml/preferences.xml
index 8d064587..27bf2a8a 100755
--- a/org.fox.ttrss/src/main/res/xml/preferences.xml
+++ b/org.fox.ttrss/src/main/res/xml/preferences.xml
@@ -44,13 +44,7 @@
android:title="@string/sort_feeds_by_unread" />
<SwitchPreferenceCompat
- android:defaultValue="true"
- android:key="enable_cats"
- android:title="@string/enable_cats" />
-
- <SwitchPreferenceCompat
android:defaultValue="false"
- android:dependency="enable_cats"
android:key="browse_cats_like_feeds"
android:summary="@string/browse_cats_like_feeds_summary"
android:title="@string/browse_cats_like_feeds" />