summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorMatej Drobnič <matej@matejdro.com>2023-10-22 16:53:41 +0200
committerGitHub <noreply@github.com>2023-10-22 16:53:41 +0200
commit346365b8d0aef14e79da921056d9438fe9d2663e (patch)
tree5fa0082c45493ffa16ffd0a63a3db722fd3206a1 /core/src
parentfa75317bce95bdae152fa1171894d4c025e3921c (diff)
downloadAntennaPod-346365b8d0aef14e79da921056d9438fe9d2663e.zip
Delete local feed episodes (#6400)
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java128
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/FeedUtil.java13
4 files changed, 97 insertions, 53 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java b/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
index 03881ee4f..52b2d61dc 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
@@ -37,7 +37,6 @@ import de.danoeh.antennapod.model.download.DownloadError;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
-import de.danoeh.antennapod.model.feed.FeedPreferences;
import de.danoeh.antennapod.model.playback.MediaType;
import de.danoeh.antennapod.parser.feed.util.MimeTypeUtils;
import de.danoeh.antennapod.parser.media.id3.ID3ReaderException;
@@ -124,13 +123,9 @@ public class LocalFeedUpdater {
feed.setImageUrl(getImageUrl(allFiles, folderUri));
feed.getPreferences().setAutoDownload(false);
- feed.getPreferences().setAutoDeleteAction(FeedPreferences.AutoDeleteAction.NEVER);
feed.setDescription(context.getString(R.string.local_feed_description));
feed.setAuthor(context.getString(R.string.local_folder));
- if (newItems.isEmpty()) {
- throw new IOException("Empty folder. Make sure that the folder is accessible and contains media files.");
- }
DBTasks.updateFeed(context, feed, true);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
index b98dbfad7..c82d6f975 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
@@ -68,6 +68,7 @@ import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.FeedSearcher;
import de.danoeh.antennapod.core.sync.queue.SynchronizationQueueSink;
import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.core.util.FeedUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
@@ -1103,7 +1104,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
FeedPreferences.AutoDeleteAction action =
item.getFeed().getPreferences().getCurrentAutoDelete();
boolean shouldAutoDelete = action == FeedPreferences.AutoDeleteAction.ALWAYS
- || (action == FeedPreferences.AutoDeleteAction.GLOBAL && UserPreferences.isAutoDelete());
+ || (action == FeedPreferences.AutoDeleteAction.GLOBAL
+ && FeedUtil.shouldAutoDeleteItemsOnThatFeed(item.getFeed()));
if (shouldAutoDelete && (!item.isTagged(FeedItem.TAG_FAVORITE)
|| !UserPreferences.shouldFavoriteKeepEpisode())) {
DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId());
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
index 11e82af27..f7e8592e1 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
@@ -2,15 +2,22 @@ package de.danoeh.antennapod.core.storage;
import android.app.backup.BackupManager;
import android.content.Context;
+import android.net.Uri;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationManagerCompat;
+import androidx.documentfile.provider.DocumentFile;
+import com.google.common.util.concurrent.Futures;
+
+import de.danoeh.antennapod.core.event.DownloadLogEvent;
+import de.danoeh.antennapod.core.feed.LocalFeedUpdater;
import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceInterface;
import de.danoeh.antennapod.storage.database.PodDBAdapter;
+
import org.greenrobot.eventbus.EventBus;
import java.io.File;
@@ -25,7 +32,6 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.event.DownloadLogEvent;
import de.danoeh.antennapod.event.FavoritesEvent;
import de.danoeh.antennapod.event.FeedItemEvent;
import de.danoeh.antennapod.event.FeedListUpdateEvent;
@@ -94,7 +100,7 @@ public class DBWriter {
*/
public static Future<?> deleteFeedMediaOfItem(@NonNull final Context context,
final long mediaId) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final FeedMedia media = DBReader.getFeedMedia(mediaId);
if (media != null) {
boolean result = deleteFeedMediaSynchronous(context, media);
@@ -106,10 +112,10 @@ public class DBWriter {
});
}
- private static boolean deleteFeedMediaSynchronous(
- @NonNull Context context, @NonNull FeedMedia media) {
+ private static boolean deleteFeedMediaSynchronous(@NonNull Context context, @NonNull FeedMedia media) {
Log.i(TAG, String.format(Locale.US, "Requested to delete FeedMedia [id=%d, title=%s, downloaded=%s",
media.getId(), media.getEpisodeTitle(), media.isDownloaded()));
+ boolean localDelete = false;
if (media.isDownloaded()) {
// delete downloaded media file
File mediaFile = new File(media.getFile_url());
@@ -125,23 +131,38 @@ public class DBWriter {
adapter.open();
adapter.setMedia(media);
adapter.close();
+ } else if (media.getFile_url().startsWith("content://")) {
+ // Local feed
+ DocumentFile documentFile = DocumentFile.fromSingleUri(
+ context, Uri.parse(media.getFile_url()));
+ if (documentFile == null || !documentFile.exists() || !documentFile.delete()) {
+ EventBus.getDefault().post(new MessageEvent(context.getString(R.string.delete_local_failed)));
+ return false;
+ }
+ localDelete = true;
+ }
- if (media.getId() == PlaybackPreferences.getCurrentlyPlayingFeedMediaId()) {
- PlaybackPreferences.writeNoMediaPlaying();
- IntentUtils.sendLocalBroadcast(context, PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE);
+ if (media.getId() == PlaybackPreferences.getCurrentlyPlayingFeedMediaId()) {
+ PlaybackPreferences.writeNoMediaPlaying();
+ IntentUtils.sendLocalBroadcast(context, PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE);
- NotificationManagerCompat nm = NotificationManagerCompat.from(context);
- nm.cancel(R.id.notification_playing);
- }
+ NotificationManagerCompat nm = NotificationManagerCompat.from(context);
+ nm.cancel(R.id.notification_playing);
+ }
+ if (localDelete) {
+ // Do full update of this feed to get rid of the item
+ LocalFeedUpdater.updateFeed(media.getItem().getFeed(), context.getApplicationContext(), null);
+ } else {
// Gpodder: queue delete action for synchronization
FeedItem item = media.getItem();
EpisodeAction action = new EpisodeAction.Builder(item, EpisodeAction.DELETE)
.currentTimestamp()
.build();
SynchronizationQueueSink.enqueueEpisodeActionIfSynchronizationIsActive(context, action);
+
+ EventBus.getDefault().post(FeedItemEvent.updated(media.getItem()));
}
- EventBus.getDefault().post(FeedItemEvent.updated(media.getItem()));
return true;
}
@@ -152,7 +173,7 @@ public class DBWriter {
* @param feedId ID of the Feed that should be deleted.
*/
public static Future<?> deleteFeed(final Context context, final long feedId) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final Feed feed = DBReader.getFeed(feedId);
if (feed == null) {
return;
@@ -183,7 +204,7 @@ public class DBWriter {
*/
@NonNull
public static Future<?> deleteFeedItems(@NonNull Context context, @NonNull List<FeedItem> items) {
- return dbExec.submit(() -> deleteFeedItemsSynchronous(context, items));
+ return runOnDbThread(() -> deleteFeedItemsSynchronous(context, items));
}
/**
@@ -235,7 +256,7 @@ public class DBWriter {
* Deletes the entire playback history.
*/
public static Future<?> clearPlaybackHistory() {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.clearPlaybackHistory();
@@ -248,7 +269,7 @@ public class DBWriter {
* Deletes the entire download log.
*/
public static Future<?> clearDownloadLog() {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.clearDownloadLog();
@@ -281,7 +302,7 @@ public class DBWriter {
* @param date PlaybackCompletionDate for <code>media</code>
*/
public static Future<?> addItemToPlaybackHistory(final FeedMedia media, Date date) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
Log.d(TAG, "Adding item to playback history");
media.setPlaybackCompletionDate(date);
@@ -300,7 +321,7 @@ public class DBWriter {
* @param status The DownloadStatus object.
*/
public static Future<?> addDownloadStatus(final DownloadResult status) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setDownloadStatus(status);
@@ -322,7 +343,7 @@ public class DBWriter {
*/
public static Future<?> addQueueItemAt(final Context context, final long itemId,
final int index, final boolean performAutoDownload) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
final List<FeedItem> queue = DBReader.getQueue(adapter);
@@ -393,7 +414,7 @@ public class DBWriter {
*/
public static Future<?> addQueueItem(final Context context, final boolean performAutoDownload,
final boolean markAsUnplayed, final long... itemIds) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
if (itemIds.length < 1) {
return;
}
@@ -476,7 +497,7 @@ public class DBWriter {
* Removes all FeedItem objects from the queue.
*/
public static Future<?> clearQueue() {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.clearQueue();
@@ -495,12 +516,12 @@ public class DBWriter {
*/
public static Future<?> removeQueueItem(final Context context,
final boolean performAutoDownload, final FeedItem item) {
- return dbExec.submit(() -> removeQueueItemSynchronous(context, performAutoDownload, item.getId()));
+ return runOnDbThread(() -> removeQueueItemSynchronous(context, performAutoDownload, item.getId()));
}
public static Future<?> removeQueueItem(final Context context, final boolean performAutoDownload,
final long... itemIds) {
- return dbExec.submit(() -> removeQueueItemSynchronous(context, performAutoDownload, itemIds));
+ return runOnDbThread(() -> removeQueueItemSynchronous(context, performAutoDownload, itemIds));
}
private static void removeQueueItemSynchronous(final Context context,
@@ -562,7 +583,7 @@ public class DBWriter {
}
public static Future<?> addFavoriteItem(final FeedItem item) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance().open();
adapter.addFavoriteItem(item);
adapter.close();
@@ -573,7 +594,7 @@ public class DBWriter {
}
public static Future<?> removeFavoriteItem(final FeedItem item) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance().open();
adapter.removeFavoriteItem(item);
adapter.close();
@@ -590,7 +611,7 @@ public class DBWriter {
* @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to
*/
public static Future<?> moveQueueItemToTop(final long itemId, final boolean broadcastUpdate) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
LongList queueIdList = DBReader.getQueueIDList();
int index = queueIdList.indexOf(itemId);
if (index >= 0) {
@@ -609,7 +630,7 @@ public class DBWriter {
*/
public static Future<?> moveQueueItemToBottom(final long itemId,
final boolean broadcastUpdate) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
LongList queueIdList = DBReader.getQueueIDList();
int index = queueIdList.indexOf(itemId);
if (index >= 0) {
@@ -632,7 +653,7 @@ public class DBWriter {
*/
public static Future<?> moveQueueItem(final int from,
final int to, final boolean broadcastUpdate) {
- return dbExec.submit(() -> moveQueueItemHelper(from, to, broadcastUpdate));
+ return runOnDbThread(() -> moveQueueItemHelper(from, to, broadcastUpdate));
}
/**
@@ -669,7 +690,7 @@ public class DBWriter {
}
public static Future<?> resetPagedFeedPage(Feed feed) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.resetPagedFeedPage(feed);
@@ -699,7 +720,7 @@ public class DBWriter {
*/
public static Future<?> markItemPlayed(final int played, final boolean broadcastUpdate,
final long... itemIds) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItemRead(played, itemIds);
@@ -729,7 +750,7 @@ public class DBWriter {
final int played,
final long mediaId,
final boolean resetMediaPosition) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItemRead(played, itemId, mediaId,
@@ -746,7 +767,7 @@ public class DBWriter {
* @param feedId ID of the Feed.
*/
public static Future<?> removeFeedNewFlag(final long feedId) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItems(FeedItem.NEW, FeedItem.UNPLAYED, feedId);
@@ -760,7 +781,7 @@ public class DBWriter {
* Sets the 'read'-attribute of all NEW FeedItems to UNPLAYED.
*/
public static Future<?> removeAllNewFlags() {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItems(FeedItem.NEW, FeedItem.UNPLAYED);
@@ -771,7 +792,7 @@ public class DBWriter {
}
static Future<?> addNewFeed(final Context context, final Feed... feeds) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setCompleteFeed(feeds);
@@ -789,7 +810,7 @@ public class DBWriter {
}
static Future<?> setCompleteFeed(final Feed... feeds) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setCompleteFeed(feeds);
@@ -798,7 +819,7 @@ public class DBWriter {
}
public static Future<?> setItemList(final List<FeedItem> items) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.storeFeedItemlist(items);
@@ -814,7 +835,7 @@ public class DBWriter {
* @param media The FeedMedia object.
*/
public static Future<?> setFeedMedia(final FeedMedia media) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setMedia(media);
@@ -828,7 +849,7 @@ public class DBWriter {
* @param media The FeedMedia object.
*/
public static Future<?> setFeedMediaPlaybackInformation(final FeedMedia media) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedMediaPlaybackInformation(media);
@@ -843,7 +864,7 @@ public class DBWriter {
* @param item The FeedItem object.
*/
public static Future<?> setFeedItem(final FeedItem item) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setSingleFeedItem(item);
@@ -857,7 +878,7 @@ public class DBWriter {
*/
public static Future<?> updateFeedDownloadURL(final String original, final String updated) {
Log.d(TAG, "updateFeedDownloadURL(original: " + original + ", updated: " + updated + ")");
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedDownloadUrl(original, updated);
@@ -871,7 +892,7 @@ public class DBWriter {
* @param preferences The FeedPreferences object.
*/
public static Future<?> setFeedPreferences(final FeedPreferences preferences) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedPreferences(preferences);
@@ -901,7 +922,7 @@ public class DBWriter {
*/
public static Future<?> setFeedLastUpdateFailed(final long feedId,
final boolean lastUpdateFailed) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedLastUpdateFailed(feedId, lastUpdateFailed);
@@ -911,7 +932,7 @@ public class DBWriter {
}
public static Future<?> setFeedCustomTitle(Feed feed) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedCustomTitle(feed.getId(), feed.getCustomTitle());
@@ -930,10 +951,10 @@ public class DBWriter {
public static Future<?> reorderQueue(@Nullable SortOrder sortOrder, final boolean broadcastUpdate) {
if (sortOrder == null) {
Log.w(TAG, "reorderQueue() - sortOrder is null. Do nothing.");
- return dbExec.submit(() -> { });
+ return runOnDbThread(() -> { });
}
final Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(sortOrder);
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
final List<FeedItem> queue = DBReader.getQueue(adapter);
@@ -960,7 +981,7 @@ public class DBWriter {
public static Future<?> setFeedItemsFilter(final long feedId,
final Set<String> filterValues) {
Log.d(TAG, "setFeedItemsFilter() called with: " + "feedId = [" + feedId + "], filterValues = [" + filterValues + "]");
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItemFilter(feedId, filterValues);
@@ -974,7 +995,7 @@ public class DBWriter {
*
*/
public static Future<?> setFeedItemSortOrder(long feedId, @Nullable SortOrder sortOrder) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItemSortOrder(feedId, sortOrder);
@@ -988,11 +1009,24 @@ public class DBWriter {
*/
@NonNull
public static Future<?> resetStatistics() {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.resetAllMediaPlayedDuration();
adapter.close();
});
}
+
+ /**
+ * Submit to the DB thread only if caller is not already on the DB thread. Otherwise,
+ * just execute synchronously
+ */
+ private static Future<?> runOnDbThread(Runnable runnable) {
+ if ("DatabaseExecutor".equals(Thread.currentThread().getName())) {
+ runnable.run();
+ return Futures.immediateFuture(null);
+ } else {
+ return dbExec.submit(runnable);
+ }
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FeedUtil.java b/core/src/main/java/de/danoeh/antennapod/core/util/FeedUtil.java
new file mode 100644
index 000000000..201207816
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/FeedUtil.java
@@ -0,0 +1,13 @@
+package de.danoeh.antennapod.core.util;
+
+import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.storage.preferences.UserPreferences;
+
+public abstract class FeedUtil {
+ public static boolean shouldAutoDeleteItemsOnThatFeed(Feed feed) {
+ if (!UserPreferences.isAutoDelete()) {
+ return false;
+ }
+ return !feed.isLocalFeed() || UserPreferences.isAutoDeleteLocal();
+ }
+}