From 228d6704447ab60804d0444be08a76db066aa998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Drobni=C4=8D?= Date: Sat, 17 Dec 2022 10:03:15 +0100 Subject: [PATCH] add option to automatically mark filtered episodes as played --- .../dialog/EpisodeFilterDialog.java | 11 +++++++++- .../main/res/layout/episode_filter_dialog.xml | 6 +++++ .../storage/AutomaticDownloadAlgorithm.java | 17 +++++++++----- .../antennapod/model/feed/FeedFilter.java | 22 ++++++++++++++++--- .../storage/database/DBUpgrader.java | 4 ++++ .../storage/database/PodDBAdapter.java | 6 ++++- .../mapper/FeedPreferencesCursorMapper.java | 4 +++- ui/i18n/src/main/res/values/strings.xml | 1 + 8 files changed, 60 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodeFilterDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodeFilterDialog.java index 2aa3ab31cee..f28388fbe0a 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodeFilterDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodeFilterDialog.java @@ -4,8 +4,11 @@ import android.content.DialogInterface; import android.text.TextUtils; import android.view.LayoutInflater; + import androidx.recyclerview.widget.GridLayoutManager; + import com.google.android.material.dialog.MaterialAlertDialogBuilder; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.adapter.SimpleChipAdapter; import de.danoeh.antennapod.databinding.EpisodeFilterDialogBinding; @@ -42,6 +45,9 @@ public EpisodeFilterDialog(Context context, FeedFilter filter) { termList = filter.getIncludeFilter(); viewBinding.includeRadio.setChecked(true); } + + viewBinding.markAsPlayedCheckBox.setChecked(filter.isMarkExcludedAsPlayed()); + setupWordsList(); setNegativeButton(R.string.cancel_label, null); @@ -95,7 +101,10 @@ private void onConfirmClick(DialogInterface dialog, int which) { } else { excludeFilter = toFilterString(termList); } - onConfirmed(new FeedFilter(includeFilter, excludeFilter, minimalDuration)); + boolean markExcludedAsRead = viewBinding.markAsPlayedCheckBox.isChecked(); + onConfirmed( + new FeedFilter(includeFilter, excludeFilter, minimalDuration, markExcludedAsRead) + ); } private String toFilterString(List words) { diff --git a/app/src/main/res/layout/episode_filter_dialog.xml b/app/src/main/res/layout/episode_filter_dialog.xml index 938589c5a11..865283d6597 100644 --- a/app/src/main/res/layout/episode_filter_dialog.xml +++ b/app/src/main/res/layout/episode_filter_dialog.xml @@ -94,6 +94,12 @@ + + diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/AutomaticDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/AutomaticDownloadAlgorithm.java index 5fbbbbc19be..157c98e38c2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/AutomaticDownloadAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/AutomaticDownloadAlgorithm.java @@ -51,17 +51,20 @@ public Runnable autoDownloadUndownloadedItems(final Context context) { Log.d(TAG, "Performing auto-dl of undownloaded episodes"); List candidates; + List markAsPlayedCandidates; final List queue = DBReader.getQueue(); final List newItems = DBReader.getNewItemsList(0, Integer.MAX_VALUE); candidates = new ArrayList<>(queue.size() + newItems.size()); + markAsPlayedCandidates = new ArrayList<>(queue.size() + newItems.size()); candidates.addAll(queue); for (FeedItem newItem : newItems) { FeedPreferences feedPrefs = newItem.getFeed().getPreferences(); - if (feedPrefs.getAutoDownload() - && !candidates.contains(newItem) - && feedPrefs.getFilter().shouldAutoDownload(newItem)) { - candidates.add(newItem); - } + if (feedPrefs.getAutoDownload() && !candidates.contains(newItem)) + if (feedPrefs.getFilter().shouldAutoDownload(newItem)) { + candidates.add(newItem); + } else if (feedPrefs.getFilter().isMarkExcludedAsPlayed()) { + markAsPlayedCandidates.add(newItem); + } } // filter items that are not auto downloadable @@ -102,6 +105,10 @@ public Runnable autoDownloadUndownloadedItems(final Context context) { } DownloadServiceInterface.get().download(context, false, requests.toArray(new DownloadRequest[0])); } + + for (FeedItem itemToMarkAsPlayed: markAsPlayedCandidates) { + DBWriter.markItemPlayed(itemToMarkAsPlayed, FeedItem.PLAYED, true); + } } }; } diff --git a/model/src/main/java/de/danoeh/antennapod/model/feed/FeedFilter.java b/model/src/main/java/de/danoeh/antennapod/model/feed/FeedFilter.java index f537f33e2e4..5d0fa28b8d0 100644 --- a/model/src/main/java/de/danoeh/antennapod/model/feed/FeedFilter.java +++ b/model/src/main/java/de/danoeh/antennapod/model/feed/FeedFilter.java @@ -12,11 +12,18 @@ public class FeedFilter implements Serializable { private final String excludeFilter; private final int minimalDuration; + private final boolean markExcludedAsPlayed; + public FeedFilter() { - this("", "", -1); + this("", "", -1, false); } - public FeedFilter(String includeFilter, String excludeFilter, int minimalDuration) { + public FeedFilter( + String includeFilter, + String excludeFilter, + int minimalDuration, + boolean markExcludedAsPlayed + ) { // We're storing the strings and not the parsed terms because // 1. It's easier to show the user exactly what they typed in this way // (we don't have to recreate it) @@ -24,10 +31,15 @@ public FeedFilter(String includeFilter, String excludeFilter, int minimalDuratio this.includeFilter = includeFilter; this.excludeFilter = excludeFilter; this.minimalDuration = minimalDuration; + this.markExcludedAsPlayed = markExcludedAsPlayed; + } + + public FeedFilter(String includeFilter, String excludeFilter, int minimalDuration) { + this(includeFilter, excludeFilter, minimalDuration, false); } public FeedFilter(String includeFilter, String excludeFilter) { - this(includeFilter, excludeFilter, -1); + this(includeFilter, excludeFilter, -1, false); } /** @@ -147,4 +159,8 @@ public boolean hasExcludeFilter() { public boolean hasMinimalDurationFilter() { return minimalDuration > -1; } + + public boolean isMarkExcludedAsPlayed() { + return markExcludedAsPlayed; + } } diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBUpgrader.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBUpgrader.java index 78eaf696481..8ff40465945 100644 --- a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBUpgrader.java +++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBUpgrader.java @@ -330,6 +330,10 @@ static void upgrade(final SQLiteDatabase db, final int oldVersion, final int new db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + " ADD COLUMN " + PodDBAdapter.KEY_PODCASTINDEX_CHAPTER_URL + " TEXT"); } + if (oldVersion < 2070000) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + PodDBAdapter.KEY_MARK_EXCLUDED_AS_PLAYED + " INTEGER DEFAULT 0;"); + } } } diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/PodDBAdapter.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/PodDBAdapter.java index 46c73120564..9e958f34d12 100644 --- a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/PodDBAdapter.java +++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/PodDBAdapter.java @@ -50,7 +50,7 @@ public class PodDBAdapter { private static final String TAG = "PodDBAdapter"; public static final String DATABASE_NAME = "Antennapod.db"; - public static final int VERSION = 2060000; + public static final int VERSION = 2070000; /** * Maximum number of arguments for IN-operator. @@ -111,6 +111,7 @@ public class PodDBAdapter { public static final String KEY_INCLUDE_FILTER = "include_filter"; public static final String KEY_EXCLUDE_FILTER = "exclude_filter"; public static final String KEY_MINIMAL_DURATION_FILTER = "minimal_duration_filter"; + public static final String KEY_MARK_EXCLUDED_AS_PLAYED = "mark_excluded_as_played"; public static final String KEY_FEED_PLAYBACK_SPEED = "feed_playback_speed"; public static final String KEY_FEED_SKIP_INTRO = "feed_skip_intro"; public static final String KEY_FEED_SKIP_ENDING = "feed_skip_ending"; @@ -145,6 +146,7 @@ public class PodDBAdapter { + KEY_INCLUDE_FILTER + " TEXT DEFAULT ''," + KEY_EXCLUDE_FILTER + " TEXT DEFAULT ''," + KEY_MINIMAL_DURATION_FILTER + " INTEGER DEFAULT -1," + + KEY_MARK_EXCLUDED_AS_PLAYED + " INTEGER DEFAULT -1," + KEY_KEEP_UPDATED + " INTEGER DEFAULT 1," + KEY_IS_PAGED + " INTEGER DEFAULT 0," + KEY_NEXT_PAGE_LINK + " TEXT," @@ -303,6 +305,7 @@ public class PodDBAdapter { + TABLE_NAME_FEEDS + "." + KEY_INCLUDE_FILTER + ", " + TABLE_NAME_FEEDS + "." + KEY_EXCLUDE_FILTER + ", " + TABLE_NAME_FEEDS + "." + KEY_MINIMAL_DURATION_FILTER + ", " + + TABLE_NAME_FEEDS + "." + KEY_MARK_EXCLUDED_AS_PLAYED + ", " + TABLE_NAME_FEEDS + "." + KEY_FEED_PLAYBACK_SPEED + ", " + TABLE_NAME_FEEDS + "." + KEY_FEED_TAGS + ", " + TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_INTRO + ", " @@ -451,6 +454,7 @@ public void setFeedPreferences(FeedPreferences prefs) { values.put(KEY_INCLUDE_FILTER, prefs.getFilter().getIncludeFilterRaw()); values.put(KEY_EXCLUDE_FILTER, prefs.getFilter().getExcludeFilterRaw()); values.put(KEY_MINIMAL_DURATION_FILTER, prefs.getFilter().getMinimalDurationFilter()); + values.put(KEY_MARK_EXCLUDED_AS_PLAYED, prefs.getFilter().isMarkExcludedAsPlayed()); values.put(KEY_FEED_PLAYBACK_SPEED, prefs.getFeedPlaybackSpeed()); values.put(KEY_FEED_TAGS, prefs.getTagsAsString()); values.put(KEY_FEED_SKIP_INTRO, prefs.getFeedSkipIntro()); diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedPreferencesCursorMapper.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedPreferencesCursorMapper.java index 289bcbab83a..153d22726c0 100644 --- a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedPreferencesCursorMapper.java +++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedPreferencesCursorMapper.java @@ -30,6 +30,7 @@ public static FeedPreferences convert(@NonNull Cursor cursor) { int indexIncludeFilter = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_INCLUDE_FILTER); int indexExcludeFilter = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_EXCLUDE_FILTER); int indexMinimalDurationFilter = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_MINIMAL_DURATION_FILTER); + int indexMarkExcludedAsPlayed = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_MARK_EXCLUDED_AS_PLAYED); int indexFeedPlaybackSpeed = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_FEED_PLAYBACK_SPEED); int indexAutoSkipIntro = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_FEED_SKIP_INTRO); int indexAutoSkipEnding = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_FEED_SKIP_ENDING); @@ -49,6 +50,7 @@ public static FeedPreferences convert(@NonNull Cursor cursor) { String includeFilter = cursor.getString(indexIncludeFilter); String excludeFilter = cursor.getString(indexExcludeFilter); int minimalDurationFilter = cursor.getInt(indexMinimalDurationFilter); + boolean markExcludedAsPlayed = cursor.getInt(indexMarkExcludedAsPlayed) > 0; float feedPlaybackSpeed = cursor.getFloat(indexFeedPlaybackSpeed); int feedAutoSkipIntro = cursor.getInt(indexAutoSkipIntro); int feedAutoSkipEnding = cursor.getInt(indexAutoSkipEnding); @@ -64,7 +66,7 @@ public static FeedPreferences convert(@NonNull Cursor cursor) { volumeAdaptionSetting, username, password, - new FeedFilter(includeFilter, excludeFilter, minimalDurationFilter), + new FeedFilter(includeFilter, excludeFilter, minimalDurationFilter, markExcludedAsPlayed), feedPlaybackSpeed, feedAutoSkipIntro, feedAutoSkipEnding, diff --git a/ui/i18n/src/main/res/values/strings.xml b/ui/i18n/src/main/res/values/strings.xml index b2ec9e0fe81..304b03d9e9e 100644 --- a/ui/i18n/src/main/res/values/strings.xml +++ b/ui/i18n/src/main/res/values/strings.xml @@ -695,6 +695,7 @@ Exclude episodes containing any of the terms below Include only episodes containing any of the terms below Exclude episodes shorter than + Mark excluded episodes as played Keep Updated Include this podcast when (auto-)refreshing all podcasts Auto download is disabled in the main AntennaPod settings