summaryrefslogtreecommitdiff
path: root/org.fox.ttrss/src/main
diff options
context:
space:
mode:
authorAndrew Dolgov <fox@fakecake.org>2025-05-21 07:57:23 +0300
committerAndrew Dolgov <fox@fakecake.org>2025-05-21 07:57:23 +0300
commit0b5d49463a295ba060b8bd6ad65046496068c9dc (patch)
treecf0d21c8abca10612f5498b7e6f3fc9f488db820 /org.fox.ttrss/src/main
parentf0eafdc186eb5f5d0c05ce3df96a36414d550fe5 (diff)
drop ArticleList class, replace with instances of ArrayList/List/Collections where appropriate
Diffstat (limited to 'org.fox.ttrss/src/main')
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/Application.java5
-rw-r--r--org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleModel.java38
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/ArticlePager.java5
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java60
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/OnlineActivity.java80
-rwxr-xr-xorg.fox.ttrss/src/main/java/org/fox/ttrss/types/ArticleList.java53
-rwxr-xr-xorg.fox.ttrss/src/main/res/values/strings.xml1
7 files changed, 88 insertions, 154 deletions
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/Application.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/Application.java
index 56546a33..335815e8 100755
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/Application.java
+++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/Application.java
@@ -12,10 +12,11 @@ import org.acra.config.CoreConfigurationBuilder;
import org.acra.config.DialogConfigurationBuilder;
import org.acra.config.MailSenderConfigurationBuilder;
import org.acra.data.StringFormat;
-import org.fox.ttrss.types.ArticleList;
+import org.fox.ttrss.types.Article;
import java.util.HashMap;
import java.util.LinkedHashMap;
+import java.util.List;
public class Application extends android.app.Application {
@@ -31,7 +32,7 @@ public class Application extends android.app.Application {
return m_singleton;
}
- public static ArticleList getArticles() {
+ public static List<Article> getArticles() {
return getInstance().m_articleModel.getArticles().getValue();
}
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 366a8fa8..98d9e8ba 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
@@ -19,18 +19,19 @@ import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import org.fox.ttrss.types.Article;
-import org.fox.ttrss.types.ArticleList;
import org.fox.ttrss.types.Feed;
import java.lang.reflect.Type;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCaller {
private final String TAG = this.getClass().getSimpleName();
- @NonNull private final MutableLiveData<ArticleList> m_articles = new MutableLiveData<>(new ArticleList());
+ @NonNull private final MutableLiveData<List<Article>> m_articles = new MutableLiveData<>(new ArrayList<Article>());
private SharedPreferences m_prefs;
private final int m_responseCode = 0;
protected String m_responseMessage;
@@ -67,7 +68,7 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle
return m_lastUpdate;
}
- public LiveData<ArticleList> getArticles() {
+ public LiveData<List<Article>> getArticles() {
return m_articles;
}
@@ -83,7 +84,7 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle
m_articles.postValue(m_articles.getValue());
}
- public void update(@NonNull ArticleList articles) {
+ public void update(@NonNull List<Article> articles) {
m_articles.postValue(articles);
}
@@ -91,13 +92,14 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle
return m_activeArticle;
}
+ /** returns null if there's none or it is invalid (missing in list) */
public Article getActiveArticle() {
- ArticleList articles = m_articles.getValue();
+ List<Article> articles = m_articles.getValue();
try {
- // always get uptodate item from model list
+ // always get uptodate item from model list if possible
return articles.get(articles.indexOf(m_activeArticle.getValue()));
- } catch (ArrayIndexOutOfBoundsException e) {
+ } catch (IndexOutOfBoundsException e) {
return null;
}
}
@@ -160,7 +162,7 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle
public enum ArticlesSelection { ALL, NONE, UNREAD }
public void setSelection(@NonNull ArticlesSelection select) {
- ArticleList articles = m_articles.getValue();
+ List<Article> articles = m_articles.getValue();
for (int i = 0; i < articles.size(); i++) {
Article articleClone = new Article(articles.get(i));
@@ -178,7 +180,7 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle
private void loadInBackground() {
Log.d(TAG, this + " loadInBackground append=" + m_append + " offset=" + m_offset + " lazyLoadEnabled=" + m_lazyLoadEnabled);
- final ArticleList articlesWork = new ArticleList(m_articles.getValue());
+ final List<Article> articlesWork = new ArrayList<>(m_articles.getValue());
m_isLoading.postValue(true);
@@ -270,11 +272,13 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle
m_amountLoaded = articlesJson.size();
for (Article article : articlesJson)
- if (!articlesWork.containsId(article.id)) {
+ if (!articlesWork.contains(article)) {
article.collectMediaInfo();
article.cleanupExcerpt();
article.fixNullFields();
articlesWork.add(article);
+ } else {
+ Log.d(TAG, "duplicate:" + article);
}
if (m_firstIdChanged) {
@@ -308,14 +312,14 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle
});
}
- private int getSkip(boolean append, @NonNull ArticleList articles) {
+ private int getSkip(boolean append, @NonNull List<Article> articles) {
int skip = 0;
if (append) {
// adaptive, all_articles, marked, published, unread
String viewMode = m_prefs.getString("view_mode", "adaptive");
- int numUnread = Math.toIntExact(articles.getUnreadCount());
+ int numUnread = Math.toIntExact(getUnread(articles).size());
int numAll = Math.toIntExact(articles.size());
if ("marked".equals(viewMode)) {
@@ -408,4 +412,14 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle
startLoading(false, m_feed, m_resizeWidth);
}
}
+
+
+ public List<Article> getUnread(List<Article> articles) {
+ return articles.stream().filter(a -> { return a.unread; }).collect(Collectors.toList());
+ }
+
+ public List<Article> getSelected() {
+ return m_articles.getValue().stream().filter(a -> { return a.selected; }).collect(Collectors.toList());
+ }
+
}
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 f411b7e0..7632ea19 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
@@ -13,11 +13,12 @@ import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2;
import org.fox.ttrss.types.Article;
-import org.fox.ttrss.types.ArticleList;
import org.fox.ttrss.types.Feed;
import org.fox.ttrss.util.ArticleDiffItemCallback;
import org.fox.ttrss.util.DiffFragmentStateAdapter;
+import java.util.ArrayList;
+
public class ArticlePager extends androidx.fragment.app.Fragment {
private final String TAG = this.getClass().getSimpleName();
@@ -34,7 +35,7 @@ public class ArticlePager extends androidx.fragment.app.Fragment {
}
private void syncToSharedArticles() {
- submitList(new ArticleList(Application.getArticles()));
+ submitList(new ArrayList<>(Application.getArticles()));
}
@Override
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 fb4452db..6621a37c 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
@@ -75,7 +75,6 @@ import com.google.android.material.snackbar.Snackbar;
import org.fox.ttrss.glide.ProgressTarget;
import org.fox.ttrss.types.Article;
-import org.fox.ttrss.types.ArticleList;
import org.fox.ttrss.types.Attachment;
import org.fox.ttrss.types.Feed;
import org.fox.ttrss.util.ArticleDiffItemCallback;
@@ -84,6 +83,7 @@ import org.jsoup.nodes.Element;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
@@ -108,7 +108,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
private SharedPreferences m_prefs;
private ArticleListAdapter m_adapter;
- private final ArticleList m_readArticles = new ArticleList();
+ private final List<Article> m_readArticles = new ArrayList<>();
private HeadlinesEventListener m_listener;
private OnlineActivity m_activity;
private SwipeRefreshLayout m_swipeLayout;
@@ -164,45 +164,13 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
m_activity.shareArticle(article);
return true;
} else if (itemId == R.id.catchup_above) {
- final Article fa = article;
-
- MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext())
- .setMessage(R.string.confirm_catchup_above)
- .setPositiveButton(R.string.dialog_ok,
- (dialog, which) -> catchupAbove(fa))
- .setNegativeButton(R.string.dialog_cancel,
- (dialog, which) -> { });
-
- Dialog dialog = builder.create();
- dialog.show();
+ m_activity.confirmCatchupAbove(article);
return true;
}
Log.d(TAG, "onArticleMenuItemSelected, unhandled id=" + item.getItemId());
return false;
}
- private void catchupAbove(Article article) {
-
- ArticleList tmp = new ArticleList();
- ArticleList articles = Application.getArticles();
-
- for (Article a : articles) {
- if (article.equalsById(a))
- break;
-
- if (a.unread) {
- Article articleClone = new Article(a);
- articleClone.unread = false;
-
- tmp.add(articleClone);
- }
- }
-
- if (!tmp.isEmpty()) {
- m_activity.setArticlesUnread(tmp, Article.UPDATE_SET_FALSE);
- }
- }
-
// all onContextItemSelected are invoked in sequence so we might get a context menu for headlines, etc
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
@@ -359,7 +327,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
wasUnread = false;
}
- ArticleList tmpRemove = new ArticleList(Application.getArticles());
+ List<Article> tmpRemove = new ArrayList<>(Application.getArticles());
tmpRemove.remove(adapterPosition);
Application.getArticlesModel().update(tmpRemove);
@@ -372,7 +340,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
m_activity.saveArticleUnread(article);
}
- ArticleList tmpInsert = new ArticleList(Application.getArticles());
+ List<Article> tmpInsert = new ArrayList<>(Application.getArticles());
tmpInsert.add(adapterPosition, article);
Application.getArticlesModel().update(tmpInsert);
@@ -392,7 +360,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
m_list.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
- public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
ArticleModel model = Application.getArticlesModel();
@@ -401,7 +369,9 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
if (!m_readArticles.isEmpty() && !m_isLazyLoading && !model.isLoading() && m_prefs.getBoolean("headlines_mark_read_scroll", false)) {
Log.d(TAG, "marking articles as read, count=" + m_readArticles.size());
- m_activity.setArticlesUnread(m_readArticles, Article.UPDATE_SET_FALSE);
+ // since we clear the list after we send the batch to mark as read, we need to pass a cloned arraylist here,
+ // otherwise nothing would get marked as read when async operation completes
+ m_activity.setArticlesUnread(new ArrayList<>(m_readArticles), Article.UPDATE_SET_FALSE);
m_readArticles.clear();
@@ -411,7 +381,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
}
@Override
- public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int firstVisibleItem = m_layoutManager.findFirstVisibleItemPosition();
@@ -425,7 +395,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
Article article = Application.getArticles().get(i);
if (article.unread && !m_readArticles.contains(article))
- m_readArticles.add(article);
+ m_readArticles.add(new Article(article));
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
@@ -478,7 +448,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
// this gets notified on network update
model.getUpdatesData().observe(getActivity(), lastUpdate -> {
if (lastUpdate > 0) {
- ArticleList tmp = new ArticleList(model.getArticles().getValue());
+ List<Article> tmp = new ArrayList<>(model.getArticles().getValue());
Log.d(TAG, "observed headlines last update=" + lastUpdate + " article count=" + tmp.size());
@@ -524,7 +494,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
model.getArticles().observe(getActivity(), articles -> {
Log.d(TAG, "observed headlines article list size=" + articles.size());
- ArticleList tmp = new ArticleList(articles);
+ List<Article> tmp = new ArrayList<>(articles);
if (m_prefs.getBoolean("headlines_mark_read_scroll", false))
tmp.add(new Article(Article.TYPE_AMR_FOOTER));
@@ -1597,9 +1567,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment {
}
private void syncToSharedArticles() {
- ArticleList tmp = new ArticleList();
-
- tmp.addAll(Application.getArticles());
+ List<Article> tmp = new ArrayList<>(Application.getArticles());
if (m_prefs.getBoolean("headlines_mark_read_scroll", false))
tmp.add(new Article(Article.TYPE_AMR_FOOTER));
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 1cdd972f..50f9d533 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
@@ -38,12 +38,13 @@ import com.google.gson.reflect.TypeToken;
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 java.lang.reflect.Type;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@@ -121,7 +122,19 @@ public class OnlineActivity extends CommonActivity {
}
}
- //protected PullToRefreshAttacher m_pullToRefreshAttacher;
+ public void confirmCatchupAbove(final Article article) {
+ MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this)
+ .setMessage(getString(R.string.confirm_catchup_above_title, article.title))
+ .setPositiveButton(R.string.dialog_ok,
+ (dialog, which) -> catchupAbove(article))
+ .setNegativeButton(R.string.dialog_cancel,
+ (dialog, which) -> { });
+
+ Dialog dialog = builder.create();
+ dialog.show();
+ }
+
+ //protected PullToRefreshAttacher m_pullToRefreshAttacher;
protected static abstract class OnLoginFinishedListener {
public abstract void OnLoginSuccess();
@@ -550,7 +563,7 @@ public class OnlineActivity extends CommonActivity {
}
return true;
} else if (itemId == R.id.selection_toggle_unread) {
- ArticleList selected = Application.getArticles().getSelected();
+ List<Article> selected = Application.getArticlesModel().getSelected();
if (!selected.isEmpty()) {
for (Article a : selected) {
@@ -562,7 +575,7 @@ public class OnlineActivity extends CommonActivity {
}
return true;
} else if (itemId == R.id.selection_toggle_marked) {
- ArticleList selected = Application.getArticles().getSelected();
+ List<Article> selected = Application.getArticlesModel().getSelected();
if (!selected.isEmpty()) {
for (Article a : selected) {
@@ -574,7 +587,7 @@ public class OnlineActivity extends CommonActivity {
}
return true;
} else if (itemId == R.id.selection_toggle_published) {
- ArticleList selected = Application.getArticles().getSelected();
+ List<Article> selected = Application.getArticlesModel().getSelected();
if (!selected.isEmpty()) {
for (Article a : selected) {
@@ -594,18 +607,9 @@ public class OnlineActivity extends CommonActivity {
}
return true;
} else if (itemId == R.id.catchup_above) {
- MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this)
- .setMessage(R.string.confirm_catchup_above)
- .setPositiveButton(R.string.dialog_ok,
- (dialog, which) -> catchupAbove())
- .setNegativeButton(R.string.dialog_cancel,
- (dialog, which) -> {
-
- });
-
- Dialog dialog = builder.create();
- dialog.show();
-
+ if (activeArticle != null) {
+ confirmCatchupAbove(activeArticle);
+ }
return true;
} else if (itemId == R.id.article_set_labels) {
if (getApiLevel() != 7) {
@@ -621,14 +625,12 @@ public class OnlineActivity extends CommonActivity {
return super.onOptionsItemSelected(item);
}
- private void catchupAbove() {
- Article activeArticle = Application.getArticlesModel().getActiveArticle();
-
- if (activeArticle != null) {
- ArticleList tmp = new ArticleList();
+ protected void catchupAbove(final Article startingArticle) {
+ if (startingArticle != null) {
+ List<Article> tmp = new ArrayList<>();
for (Article a : Application.getArticles()) {
- if (a.id == activeArticle.id)
+ if (a.id == startingArticle.id)
break;
Article articleClone = new Article(a);
@@ -637,8 +639,6 @@ public class OnlineActivity extends CommonActivity {
articleClone.unread = false;
tmp.add(articleClone);
-
- Application.getArticlesModel().update(articleClone);
}
}
@@ -919,53 +919,53 @@ public class OnlineActivity extends CommonActivity {
}
public void saveArticleUnread(final Article article) {
- setArticlesField(new ArticleList(article), Article.UPDATE_FIELD_UNREAD,
+ setArticlesField(Collections.singletonList(article), Article.UPDATE_FIELD_UNREAD,
article.unread ? Article.UPDATE_SET_TRUE : Article.UPDATE_SET_FALSE);
}
public void saveArticleScore(final Article article) {
- setArticlesField(new ArticleList(article), Article.UPDATE_FIELD_SCORE, Article.UPDATE_SET_TRUE);
+ setArticlesField(Collections.singletonList(article), Article.UPDATE_FIELD_SCORE, Article.UPDATE_SET_TRUE);
}
public void saveArticleMarked(final Article article) {
- setArticlesField(new ArticleList(article), Article.UPDATE_FIELD_MARKED,
+ setArticlesField(Collections.singletonList(article), Article.UPDATE_FIELD_MARKED,
article.marked ? Article.UPDATE_SET_TRUE : Article.UPDATE_SET_FALSE);
}
public void saveArticlePublished(final Article article) {
- setArticlesField(new ArticleList(article), Article.UPDATE_FIELD_PUBLISHED,
+ setArticlesField(Collections.singletonList(article), Article.UPDATE_FIELD_PUBLISHED,
article.published ? Article.UPDATE_SET_TRUE : Article.UPDATE_SET_FALSE);
}
public void saveArticleNote(final Article article, final String note) {
- setArticlesField(new ArticleList(article), Article.UPDATE_FIELD_NOTE, Article.UPDATE_SET_TRUE);
+ setArticlesField(Collections.singletonList(article), Article.UPDATE_FIELD_NOTE, Article.UPDATE_SET_TRUE);
}
- public void toggleArticlesMarked(final ArticleList articles) {
+ public void toggleArticlesMarked(final List<Article> articles) {
setArticlesMarked(articles, Article.UPDATE_TOGGLE);
}
- public void setArticlesMarked(final ArticleList articles, int mode) {
+ public void setArticlesMarked(final List<Article> articles, int mode) {
setArticlesField(articles, Article.UPDATE_FIELD_MARKED, mode);
}
- public void toggleArticlesUnread(final ArticleList articles) {
+ public void toggleArticlesUnread(final List<Article> articles) {
setArticlesUnread(articles, Article.UPDATE_FIELD_UNREAD);
}
- public void setArticlesUnread(final ArticleList articles, int mode) {
+ public void setArticlesUnread(final List<Article> articles, int mode) {
setArticlesField(articles, Article.UPDATE_FIELD_UNREAD, mode);
}
- public void toggleArticlesPublished(final ArticleList articles) {
+ public void toggleArticlesPublished(final List<Article> articles) {
setArticlesPublished(articles, Article.UPDATE_TOGGLE);
}
- public void setArticlesPublished(final ArticleList articles, int mode) {
+ public void setArticlesPublished(final List<Article> articles, int mode) {
setArticlesField(articles, Article.UPDATE_FIELD_PUBLISHED, mode);
}
- public void setArticlesField(final ArticleList articles, int field, int mode) {
+ public void setArticlesField(final List<Article> articles, int field, int mode) {
ApiRequest req = new ApiRequest(getApplicationContext()) {
protected void onPostExecute(JsonElement result) {
if (m_lastError == ApiCommon.ApiError.SUCCESS) {
@@ -1319,8 +1319,10 @@ public class OnlineActivity extends CommonActivity {
}
public void enableActionModeObserver() {
- Application.getArticlesModel().getArticles().observe(this, (articles -> {
- int selectedCount = articles.getSelectedCount();
+ ArticleModel model = Application.getArticlesModel();
+
+ model.getArticles().observe(this, (articles -> {
+ int selectedCount = model.getSelected().size();
Log.d(TAG, "observed selected articles=" + selectedCount);
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/types/ArticleList.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/types/ArticleList.java
deleted file mode 100755
index 89530231..00000000
--- a/org.fox.ttrss/src/main/java/org/fox/ttrss/types/ArticleList.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.fox.ttrss.types;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.stream.Collectors;
-
-public class ArticleList extends CopyOnWriteArrayList<Article> {
- public boolean containsId(int id) {
- return findById(id) != null;
- }
-
- public boolean contains(Article article) {
- return containsId(article.id);
- }
-
- public Article findById(int id) {
- for (Article a : this) {
- if (a.id == id)
- return a;
- }
- return null;
- }
-
- public ArticleList(Article... articles) {
- super();
-
- addAll(Arrays.asList(articles));
- }
-
- public ArticleList() { }
-
- public ArticleList(ArticleList clone) {
- this.addAll(clone);
- }
-
- public int getUnreadCount() {
- return getUnread().size();
- }
-
- public ArticleList getUnread() {
- return this.stream().filter(a -> { return a.unread; }).collect(Collectors.toCollection(ArticleList::new));
- }
-
- public ArticleList getSelected() {
- return this.stream().filter(a -> { return a.selected; }).collect(Collectors.toCollection(ArticleList::new));
- }
-
- public int getSelectedCount() {
- return getSelected().size();
- }
-
-} \ No newline at end of file
diff --git a/org.fox.ttrss/src/main/res/values/strings.xml b/org.fox.ttrss/src/main/res/values/strings.xml
index e3111027..46001904 100755
--- a/org.fox.ttrss/src/main/res/values/strings.xml
+++ b/org.fox.ttrss/src/main/res/values/strings.xml
@@ -250,6 +250,7 @@
<string name="prefs_opening_links">Opening links</string>
<string name="open_with">Open with…</string>
<string name="confirm_catchup_above">Mark articles as read?</string>
+ <string name="confirm_catchup_above_title">Mark all articles above \"%1s\" as read?</string>
<string name="dialog_ok">OK</string>
<string name="headline_undo_row_button">UNDO</string>
<string name="headline_undo_row_prompt">Marked as read</string>