diff options
author | Matej Drobnič <matej@matejdro.com> | 2023-10-22 16:53:41 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-22 16:53:41 +0200 |
commit | 346365b8d0aef14e79da921056d9438fe9d2663e (patch) | |
tree | 5fa0082c45493ffa16ffd0a63a3db722fd3206a1 /core/src | |
parent | fa75317bce95bdae152fa1171894d4c025e3921c (diff) | |
download | AntennaPod-346365b8d0aef14e79da921056d9438fe9d2663e.zip |
Delete local feed episodes (#6400)
Diffstat (limited to 'core/src')
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(); + } +} |