Merge pull request #4693 from spacecowboy/cleanup-space-needed
Added new cleanup option: when not favorited
This commit is contained in:
commit
ded779d0c9
|
@ -15,6 +15,7 @@ import de.danoeh.antennapod.core.storage.APCleanupAlgorithm;
|
|||
import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.ExceptFavoriteCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.fragment.EpisodesFragment;
|
||||
import de.danoeh.antennapod.fragment.QueueFragment;
|
||||
import de.danoeh.antennapod.fragment.SubscriptionFragment;
|
||||
|
@ -371,6 +372,17 @@ public class PreferencesTest {
|
|||
.until(() -> enableAutodownloadOnBattery == UserPreferences.isEnableAutodownloadOnBattery());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEpisodeCleanupFavoriteOnly() {
|
||||
clickPreference(R.string.network_pref);
|
||||
onView(withText(R.string.pref_automatic_download_title)).perform(click());
|
||||
onView(withText(R.string.pref_episode_cleanup_title)).perform(click());
|
||||
onView(isRoot()).perform(waitForView(withText(R.string.episode_cleanup_except_favorite_removal), 1000));
|
||||
onView(withText(R.string.episode_cleanup_except_favorite_removal)).perform(click());
|
||||
Awaitility.await().atMost(1000, MILLISECONDS)
|
||||
.until(() -> UserPreferences.getEpisodeCleanupAlgorithm() instanceof ExceptFavoriteCleanupAlgorithm);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEpisodeCleanupQueueOnly() {
|
||||
clickPreference(R.string.network_pref);
|
||||
|
|
|
@ -174,7 +174,9 @@ public class AutoDownloadPreferencesFragment extends PreferenceFragmentCompat {
|
|||
String[] entries = new String[values.length];
|
||||
for (int x = 0; x < values.length; x++) {
|
||||
int v = Integer.parseInt(values[x]);
|
||||
if (v == UserPreferences.EPISODE_CLEANUP_QUEUE) {
|
||||
if (v == UserPreferences.EPISODE_CLEANUP_EXCEPT_FAVORITE) {
|
||||
entries[x] = res.getString(R.string.episode_cleanup_except_favorite_removal);
|
||||
} else if (v == UserPreferences.EPISODE_CLEANUP_QUEUE) {
|
||||
entries[x] = res.getString(R.string.episode_cleanup_queue_removal);
|
||||
} else if (v == UserPreferences.EPISODE_CLEANUP_NULL){
|
||||
entries[x] = res.getString(R.string.episode_cleanup_never);
|
||||
|
|
|
@ -36,6 +36,7 @@ import de.danoeh.antennapod.core.feed.MediaType;
|
|||
import de.danoeh.antennapod.core.feed.SubscriptionsFilter;
|
||||
import de.danoeh.antennapod.core.service.download.ProxyConfig;
|
||||
import de.danoeh.antennapod.core.storage.APCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.ExceptFavoriteCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm;
|
||||
|
@ -137,6 +138,7 @@ public class UserPreferences {
|
|||
public static final String PREF_CAST_ENABLED = "prefCast"; //Used for enabling Chromecast support
|
||||
public static final int EPISODE_CLEANUP_QUEUE = -1;
|
||||
public static final int EPISODE_CLEANUP_NULL = -2;
|
||||
public static final int EPISODE_CLEANUP_EXCEPT_FAVORITE = -3;
|
||||
public static final int EPISODE_CLEANUP_DEFAULT = 0;
|
||||
|
||||
// Constants
|
||||
|
@ -882,7 +884,9 @@ public class UserPreferences {
|
|||
return new APNullCleanupAlgorithm();
|
||||
}
|
||||
int cleanupValue = getEpisodeCleanupValue();
|
||||
if (cleanupValue == EPISODE_CLEANUP_QUEUE) {
|
||||
if (cleanupValue == EPISODE_CLEANUP_EXCEPT_FAVORITE) {
|
||||
return new ExceptFavoriteCleanupAlgorithm();
|
||||
} else if (cleanupValue == EPISODE_CLEANUP_QUEUE) {
|
||||
return new APQueueCleanupAlgorithm();
|
||||
} else if (cleanupValue == EPISODE_CLEANUP_NULL) {
|
||||
return new APNullCleanupAlgorithm();
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
|
||||
/**
|
||||
* A cleanup algorithm that removes any item that isn't a favorite but only if space is needed.
|
||||
*/
|
||||
public class ExceptFavoriteCleanupAlgorithm extends EpisodeCleanupAlgorithm {
|
||||
|
||||
private static final String TAG = "ExceptFavCleanupAlgo";
|
||||
|
||||
/**
|
||||
* The maximum number of episodes that could be cleaned up.
|
||||
*
|
||||
* @return the number of episodes that *could* be cleaned up, if needed
|
||||
*/
|
||||
public int getReclaimableItems() {
|
||||
return getCandidates().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int performCleanup(Context context, int numberOfEpisodesToDelete) {
|
||||
List<FeedItem> candidates = getCandidates();
|
||||
List<FeedItem> delete;
|
||||
|
||||
// in the absence of better data, we'll sort by item publication date
|
||||
Collections.sort(candidates, (lhs, rhs) -> {
|
||||
Date l = lhs.getPubDate();
|
||||
Date r = rhs.getPubDate();
|
||||
|
||||
if (l != null && r != null) {
|
||||
return l.compareTo(r);
|
||||
} else {
|
||||
// No date - compare by id which should be always incremented
|
||||
return Long.compare(lhs.getId(), rhs.getId());
|
||||
}
|
||||
});
|
||||
|
||||
if (candidates.size() > numberOfEpisodesToDelete) {
|
||||
delete = candidates.subList(0, numberOfEpisodesToDelete);
|
||||
} else {
|
||||
delete = candidates;
|
||||
}
|
||||
|
||||
for (FeedItem item : delete) {
|
||||
try {
|
||||
DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
int counter = delete.size();
|
||||
Log.i(TAG, String.format(Locale.US,
|
||||
"Auto-delete deleted %d episodes (%d requested)", counter,
|
||||
numberOfEpisodesToDelete));
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<FeedItem> getCandidates() {
|
||||
List<FeedItem> candidates = new ArrayList<>();
|
||||
List<FeedItem> downloadedItems = DBReader.getDownloadedItems();
|
||||
for (FeedItem item : downloadedItems) {
|
||||
if (item.hasMedia()
|
||||
&& item.getMedia().isDownloaded()
|
||||
&& !item.isTagged(FeedItem.TAG_FAVORITE)) {
|
||||
candidates.add(item);
|
||||
}
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultCleanupParameter() {
|
||||
int cacheSize = UserPreferences.getEpisodeCacheSize();
|
||||
if (cacheSize != UserPreferences.getEpisodeCacheSizeUnlimited()) {
|
||||
int downloadedEpisodes = DBReader.getNumberOfDownloadedEpisodes();
|
||||
if (downloadedEpisodes > cacheSize) {
|
||||
return downloadedEpisodes - cacheSize;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -96,6 +96,7 @@
|
|||
</string-array>
|
||||
|
||||
<string-array name="episode_cleanup_entries">
|
||||
<item>@string/episode_cleanup_except_favorite_removal</item>
|
||||
<item>@string/episode_cleanup_queue_removal</item>
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
|
@ -133,6 +134,7 @@
|
|||
</string-array>
|
||||
|
||||
<string-array name="episode_cleanup_values">
|
||||
<item>-3</item>
|
||||
<item>-1</item>
|
||||
<item>0</item>
|
||||
<item>12</item>
|
||||
|
|
|
@ -116,6 +116,7 @@
|
|||
<string name="feed_auto_download_never">Never</string>
|
||||
<string name="send_label">Send…</string>
|
||||
<string name="episode_cleanup_never">Never</string>
|
||||
<string name="episode_cleanup_except_favorite_removal">When not favorited</string>
|
||||
<string name="episode_cleanup_queue_removal">When not in queue</string>
|
||||
<string name="episode_cleanup_after_listening">After finishing</string>
|
||||
<plurals name="episode_cleanup_hours_after_listening">
|
||||
|
@ -387,7 +388,7 @@
|
|||
<string name="preference_search_clear_history">Clear history</string>
|
||||
<string name="media_player">Media player</string>
|
||||
<string name="pref_episode_cleanup_title">Episode Cleanup</string>
|
||||
<string name="pref_episode_cleanup_summary">Episodes that aren\'t in the queue and aren\'t favorites should be eligible for removal if Auto Download needs space for new episodes</string>
|
||||
<string name="pref_episode_cleanup_summary">Episodes that should be eligible for removal if Auto Download needs space for new episodes</string>
|
||||
<string name="pref_pauseOnDisconnect_sum">Pause playback when headphones or bluetooth are disconnected</string>
|
||||
<string name="pref_unpauseOnHeadsetReconnect_sum">Resume playback when the headphones are reconnected</string>
|
||||
<string name="pref_unpauseOnBluetoothReconnect_sum">Resume playback when bluetooth reconnects</string>
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests that the APFavoriteCleanupAlgorithm is working correctly.
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ExceptFavoriteCleanupAlgorithmTest extends DbCleanupTests {
|
||||
private final int numberOfItems = EPISODE_CACHE_SIZE * 2;
|
||||
|
||||
public ExceptFavoriteCleanupAlgorithmTest() {
|
||||
setCleanupAlgorithm(UserPreferences.EPISODE_CLEANUP_EXCEPT_FAVORITE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPerformAutoCleanupHandleUnplayed() throws IOException {
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<>();
|
||||
populateItems(numberOfItems, feed, items, files, FeedItem.UNPLAYED, false, false);
|
||||
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
if (i < EPISODE_CACHE_SIZE) {
|
||||
assertTrue("Only enough items should be deleted", files.get(i).exists());
|
||||
} else {
|
||||
assertFalse("Expected episode to be deleted", files.get(i).exists());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPerformAutoCleanupDeletesQueued() throws IOException {
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<>();
|
||||
populateItems(numberOfItems, feed, items, files, FeedItem.UNPLAYED, true, false);
|
||||
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
if (i < EPISODE_CACHE_SIZE) {
|
||||
assertTrue("Only enough items should be deleted", files.get(i).exists());
|
||||
} else {
|
||||
assertFalse("Queued episodes should be deleted", files.get(i).exists());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPerformAutoCleanupSavesFavorited() throws IOException {
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<>();
|
||||
populateItems(numberOfItems, feed, items, files, FeedItem.UNPLAYED, false, true);
|
||||
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
assertTrue("Favorite episodes should should not be deleted", files.get(i).exists());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testPerformAutoCleanupShouldNotDeleteBecauseInQueue() throws IOException {
|
||||
// Yes it should
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testPerformAutoCleanupShouldNotDeleteBecauseInQueue_withFeedsWithNoMedia() throws IOException {
|
||||
// Yes it should
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue