ability to filter episodes to include or not when autodownloading
This commit is contained in:
parent
7f02570f88
commit
0b4c41a333
|
@ -0,0 +1,119 @@
|
||||||
|
package de.test.antennapod.feed;
|
||||||
|
|
||||||
|
import android.test.AndroidTestCase;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.core.feed.FeedFilter;
|
||||||
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
|
|
||||||
|
public class FeedFilterTest extends AndroidTestCase {
|
||||||
|
|
||||||
|
public void testNullFilter() throws Exception {
|
||||||
|
FeedFilter filter = new FeedFilter();
|
||||||
|
FeedItem item = new FeedItem();
|
||||||
|
item.setTitle("Hello world");
|
||||||
|
|
||||||
|
assertTrue(!filter.excludeOnly());
|
||||||
|
assertTrue(!filter.includeOnly());
|
||||||
|
assertEquals("", filter.getExcludeFilter());
|
||||||
|
assertEquals("", filter.getIncludeFilter());
|
||||||
|
assertTrue(filter.shouldAutoDownload(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBasicIncludeFilter() throws Exception {
|
||||||
|
String includeFilter = "Hello";
|
||||||
|
FeedFilter filter = new FeedFilter(includeFilter, "");
|
||||||
|
FeedItem item = new FeedItem();
|
||||||
|
item.setTitle("Hello world");
|
||||||
|
|
||||||
|
FeedItem item2 = new FeedItem();
|
||||||
|
item2.setTitle("Don't include me");
|
||||||
|
|
||||||
|
assertTrue(!filter.excludeOnly());
|
||||||
|
assertTrue(filter.includeOnly());
|
||||||
|
assertEquals("", filter.getExcludeFilter());
|
||||||
|
assertEquals(includeFilter, filter.getIncludeFilter());
|
||||||
|
assertTrue(filter.shouldAutoDownload(item));
|
||||||
|
assertTrue(!filter.shouldAutoDownload(item2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBasicExcludeFilter() throws Exception {
|
||||||
|
String excludeFilter = "Hello";
|
||||||
|
FeedFilter filter = new FeedFilter("", excludeFilter);
|
||||||
|
FeedItem item = new FeedItem();
|
||||||
|
item.setTitle("Hello world");
|
||||||
|
|
||||||
|
FeedItem item2 = new FeedItem();
|
||||||
|
item2.setTitle("Item2");
|
||||||
|
|
||||||
|
assertTrue(filter.excludeOnly());
|
||||||
|
assertTrue(!filter.includeOnly());
|
||||||
|
assertEquals(excludeFilter, filter.getExcludeFilter());
|
||||||
|
assertEquals("", filter.getIncludeFilter());
|
||||||
|
assertTrue(!filter.shouldAutoDownload(item));
|
||||||
|
assertTrue(filter.shouldAutoDownload(item2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testComplexIncludeFilter() throws Exception {
|
||||||
|
String includeFilter = "Hello \"Two words\"";
|
||||||
|
FeedFilter filter = new FeedFilter(includeFilter, "");
|
||||||
|
FeedItem item = new FeedItem();
|
||||||
|
item.setTitle("hello world");
|
||||||
|
|
||||||
|
FeedItem item2 = new FeedItem();
|
||||||
|
item2.setTitle("Two three words");
|
||||||
|
|
||||||
|
FeedItem item3 = new FeedItem();
|
||||||
|
item3.setTitle("One two words");
|
||||||
|
|
||||||
|
assertTrue(!filter.excludeOnly());
|
||||||
|
assertTrue(filter.includeOnly());
|
||||||
|
assertEquals("", filter.getExcludeFilter());
|
||||||
|
assertEquals(includeFilter, filter.getIncludeFilter());
|
||||||
|
assertTrue(filter.shouldAutoDownload(item));
|
||||||
|
assertTrue(!filter.shouldAutoDownload(item2));
|
||||||
|
assertTrue(filter.shouldAutoDownload(item3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testComplexExcludeFilter() throws Exception {
|
||||||
|
String excludeFilter = "Hello \"Two words\"";
|
||||||
|
FeedFilter filter = new FeedFilter("", excludeFilter);
|
||||||
|
FeedItem item = new FeedItem();
|
||||||
|
item.setTitle("hello world");
|
||||||
|
|
||||||
|
FeedItem item2 = new FeedItem();
|
||||||
|
item2.setTitle("One three words");
|
||||||
|
|
||||||
|
FeedItem item3 = new FeedItem();
|
||||||
|
item3.setTitle("One two words");
|
||||||
|
|
||||||
|
assertTrue(filter.excludeOnly());
|
||||||
|
assertTrue(!filter.includeOnly());
|
||||||
|
assertEquals(excludeFilter, filter.getExcludeFilter());
|
||||||
|
assertEquals("", filter.getIncludeFilter());
|
||||||
|
assertTrue(!filter.shouldAutoDownload(item));
|
||||||
|
assertTrue(filter.shouldAutoDownload(item2));
|
||||||
|
assertTrue(!filter.shouldAutoDownload(item3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testComboFilter() throws Exception {
|
||||||
|
String includeFilter = "Hello world";
|
||||||
|
String excludeFilter = "dislike";
|
||||||
|
FeedFilter filter = new FeedFilter(includeFilter, excludeFilter);
|
||||||
|
|
||||||
|
FeedItem download = new FeedItem();
|
||||||
|
download.setTitle("Hello everyone!");
|
||||||
|
// because, while it has words from the include filter it also has exclude words
|
||||||
|
FeedItem doNotDownload = new FeedItem();
|
||||||
|
doNotDownload.setTitle("I dislike the world");
|
||||||
|
// because it has no words from the include filter
|
||||||
|
FeedItem doNotDownload2 = new FeedItem();
|
||||||
|
doNotDownload2.setTitle("no words to include");
|
||||||
|
|
||||||
|
assertTrue(filter.hasExcludeFilter());
|
||||||
|
assertTrue(filter.hasIncludeFilter());
|
||||||
|
assertTrue(filter.shouldAutoDownload(download));
|
||||||
|
assertTrue(!filter.shouldAutoDownload(doNotDownload));
|
||||||
|
assertTrue(!filter.shouldAutoDownload(doNotDownload2));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ import android.widget.CheckBox;
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import android.widget.RadioButton;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -32,6 +33,7 @@ import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||||
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
|
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
|
||||||
import de.danoeh.antennapod.core.feed.Feed;
|
import de.danoeh.antennapod.core.feed.Feed;
|
||||||
|
import de.danoeh.antennapod.core.feed.FeedFilter;
|
||||||
import de.danoeh.antennapod.core.feed.FeedPreferences;
|
import de.danoeh.antennapod.core.feed.FeedPreferences;
|
||||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
|
@ -61,8 +63,12 @@ public class FeedInfoActivity extends ActionBarActivity {
|
||||||
private TextView txtvUrl;
|
private TextView txtvUrl;
|
||||||
private EditText etxtUsername;
|
private EditText etxtUsername;
|
||||||
private EditText etxtPassword;
|
private EditText etxtPassword;
|
||||||
|
private EditText etxtFilterText;
|
||||||
|
private RadioButton rdoFilterInclude;
|
||||||
|
private RadioButton rdoFilterExclude;
|
||||||
private CheckBox cbxAutoDownload;
|
private CheckBox cbxAutoDownload;
|
||||||
private Spinner spnAutoDelete;
|
private Spinner spnAutoDelete;
|
||||||
|
private boolean filterInclude = true;
|
||||||
|
|
||||||
private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() {
|
private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -103,6 +109,17 @@ public class FeedInfoActivity extends ActionBarActivity {
|
||||||
spnAutoDelete = (Spinner) findViewById(R.id.spnAutoDelete);
|
spnAutoDelete = (Spinner) findViewById(R.id.spnAutoDelete);
|
||||||
etxtUsername = (EditText) findViewById(R.id.etxtUsername);
|
etxtUsername = (EditText) findViewById(R.id.etxtUsername);
|
||||||
etxtPassword = (EditText) findViewById(R.id.etxtPassword);
|
etxtPassword = (EditText) findViewById(R.id.etxtPassword);
|
||||||
|
etxtFilterText = (EditText) findViewById(R.id.etxtEpisodeFilterText);
|
||||||
|
rdoFilterInclude = (RadioButton) findViewById(R.id.radio_filter_include);
|
||||||
|
rdoFilterInclude.setOnClickListener(v -> {
|
||||||
|
filterInclude = true;
|
||||||
|
filterTextChanged = true;
|
||||||
|
});
|
||||||
|
rdoFilterExclude = (RadioButton) findViewById(R.id.radio_filter_exclude);
|
||||||
|
rdoFilterExclude.setOnClickListener(v -> {
|
||||||
|
filterInclude = false;
|
||||||
|
filterTextChanged = true;
|
||||||
|
});
|
||||||
|
|
||||||
txtvUrl.setOnClickListener(copyUrlToClipboard);
|
txtvUrl.setOnClickListener(copyUrlToClipboard);
|
||||||
|
|
||||||
|
@ -184,6 +201,7 @@ public class FeedInfoActivity extends ActionBarActivity {
|
||||||
feed.getPreferences().setAutoDeleteAction(auto_delete_action);// p
|
feed.getPreferences().setAutoDeleteAction(auto_delete_action);// p
|
||||||
autoDeleteChanged = true;
|
autoDeleteChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNothingSelected(AdapterView<?> parent) {
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
// Another interface callback
|
// Another interface callback
|
||||||
|
@ -197,6 +215,23 @@ public class FeedInfoActivity extends ActionBarActivity {
|
||||||
etxtUsername.addTextChangedListener(authTextWatcher);
|
etxtUsername.addTextChangedListener(authTextWatcher);
|
||||||
etxtPassword.addTextChangedListener(authTextWatcher);
|
etxtPassword.addTextChangedListener(authTextWatcher);
|
||||||
|
|
||||||
|
FeedFilter filter = prefs.getFilter();
|
||||||
|
if (filter.includeOnly()) {
|
||||||
|
etxtFilterText.setText(filter.getIncludeFilter());
|
||||||
|
rdoFilterInclude.setChecked(true);
|
||||||
|
rdoFilterExclude.setChecked(false);
|
||||||
|
} else if (filter.excludeOnly()) {
|
||||||
|
etxtFilterText.setText(filter.getExcludeFilter());
|
||||||
|
rdoFilterInclude.setChecked(false);
|
||||||
|
rdoFilterExclude.setChecked(true);
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "No filter set");
|
||||||
|
rdoFilterInclude.setChecked(false);
|
||||||
|
rdoFilterExclude.setChecked(false);
|
||||||
|
etxtFilterText.setText("");
|
||||||
|
}
|
||||||
|
etxtFilterText.addTextChangedListener(filterTextWatcher);
|
||||||
|
|
||||||
supportInvalidateOptionsMenu();
|
supportInvalidateOptionsMenu();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -227,6 +262,25 @@ public class FeedInfoActivity extends ActionBarActivity {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private boolean filterTextChanged = false;
|
||||||
|
|
||||||
|
private TextWatcher filterTextWatcher = new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
filterTextChanged = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
@ -237,11 +291,24 @@ public class FeedInfoActivity extends ActionBarActivity {
|
||||||
prefs.setUsername(etxtUsername.getText().toString());
|
prefs.setUsername(etxtUsername.getText().toString());
|
||||||
prefs.setPassword(etxtPassword.getText().toString());
|
prefs.setPassword(etxtPassword.getText().toString());
|
||||||
}
|
}
|
||||||
if (authInfoChanged || autoDeleteChanged) {
|
if (filterTextChanged) {
|
||||||
|
Log.d(TAG, "Filter info changed, saving...");
|
||||||
|
String filterText = etxtFilterText.getText().toString();
|
||||||
|
String includeString = "";
|
||||||
|
String excludeString = "";
|
||||||
|
if (filterInclude) {
|
||||||
|
includeString = filterText;
|
||||||
|
} else {
|
||||||
|
excludeString = filterText;
|
||||||
|
}
|
||||||
|
prefs.setFilter(new FeedFilter(includeString, excludeString));
|
||||||
|
}
|
||||||
|
if (authInfoChanged || autoDeleteChanged || filterTextChanged) {
|
||||||
DBWriter.setFeedPreferences(prefs);
|
DBWriter.setFeedPreferences(prefs);
|
||||||
}
|
}
|
||||||
authInfoChanged = false;
|
authInfoChanged = false;
|
||||||
autoDeleteChanged = false;
|
autoDeleteChanged = false;
|
||||||
|
filterTextChanged = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -265,6 +265,53 @@
|
||||||
|
|
||||||
</android.support.v7.widget.GridLayout>
|
</android.support.v7.widget.GridLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtvEpisodeFilters"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="@string/episode_filters_label"
|
||||||
|
android:textSize="@dimen/text_size_medium"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtvEpisodeFiltersDescription"
|
||||||
|
android:text="@string/episode_filters_description"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"/>
|
||||||
|
|
||||||
|
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
<RadioButton android:id="@+id/radio_filter_include"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/episode_filters_include"
|
||||||
|
android:onClick="onRadioButtonClicked"/>
|
||||||
|
<RadioButton android:id="@+id/radio_filter_exclude"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/episode_filters_exclude"
|
||||||
|
android:onClick="onRadioButtonClicked"/>
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etxtEpisodeFilterText"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:hint="@string/episode_filters_hint"
|
||||||
|
android:focusable="true"
|
||||||
|
android:focusableInTouchMode="true"
|
||||||
|
android:cursorVisible="true"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
style="@style/AntennaPod.TextView.Heading"
|
style="@style/AntennaPod.TextView.Heading"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
package de.danoeh.antennapod.core.feed;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class FeedFilter {
|
||||||
|
|
||||||
|
private static final String TAG = "FeedFilter";
|
||||||
|
|
||||||
|
private String includeFilter;
|
||||||
|
private String excludeFilter;
|
||||||
|
|
||||||
|
public FeedFilter() {
|
||||||
|
this("", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedFilter(String includeFilter, String excludeFilter) {
|
||||||
|
// 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)
|
||||||
|
// 2. We don't know if we'll actually be asked to parse anything anyways.
|
||||||
|
this.includeFilter = includeFilter;
|
||||||
|
this.excludeFilter = excludeFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the text in to a list of single words or quoted strings.
|
||||||
|
* Example: "One "Two Three"" returns ["One", "Two Three"]
|
||||||
|
* @param filter string to parse in to terms
|
||||||
|
* @return list of terms
|
||||||
|
*/
|
||||||
|
private List<String> parseTerms(String filter) {
|
||||||
|
// from http://stackoverflow.com/questions/7804335/split-string-on-spaces-in-java-except-if-between-quotes-i-e-treat-hello-wor
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
Matcher m = Pattern.compile("([^\"]\\S*|\".+?\")\\s*").matcher(filter);
|
||||||
|
while (m.find())
|
||||||
|
list.add(m.group(1).replace("\"", ""));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param item
|
||||||
|
* @return true if the item should be downloaded
|
||||||
|
*/
|
||||||
|
public boolean shouldAutoDownload(FeedItem item) {
|
||||||
|
|
||||||
|
List<String> includeTerms = parseTerms(includeFilter);
|
||||||
|
List<String> excludeTerms = parseTerms(excludeFilter);
|
||||||
|
|
||||||
|
if (includeTerms.size() == 0 && excludeTerms.size() == 0) {
|
||||||
|
// nothing has been specified, so include everything
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check using lowercase so the users don't have to worry about case.
|
||||||
|
String title = item.getTitle().toLowerCase();
|
||||||
|
|
||||||
|
// if it's explicitly excluded, it shouldn't be autodownloaded
|
||||||
|
// even if it has include terms
|
||||||
|
for (String term : excludeTerms) {
|
||||||
|
if (title.contains(term.trim().toLowerCase())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String term : includeTerms) {
|
||||||
|
if (title.contains(term.trim().toLowerCase())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now's the tricky bit
|
||||||
|
// if they haven't set an include filter, but they have set an exclude filter
|
||||||
|
// default to including, but if they've set both, then exclude
|
||||||
|
if (!hasIncludeFilter() && hasExcludeFilter()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIncludeFilter() {
|
||||||
|
return includeFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExcludeFilter() { return excludeFilter; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if only include is set
|
||||||
|
*/
|
||||||
|
public boolean includeOnly() {
|
||||||
|
return hasIncludeFilter() && !hasExcludeFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if only exclude is set
|
||||||
|
*/
|
||||||
|
public boolean excludeOnly() {
|
||||||
|
return hasExcludeFilter() && !hasIncludeFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasIncludeFilter() {
|
||||||
|
return includeFilter.length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasExcludeFilter() {
|
||||||
|
return excludeFilter.length() > 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.feed;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
|
@ -13,8 +14,11 @@ import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||||
*/
|
*/
|
||||||
public class FeedPreferences {
|
public class FeedPreferences {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private FeedFilter filter;
|
||||||
private long feedID;
|
private long feedID;
|
||||||
private boolean autoDownload;
|
private boolean autoDownload;
|
||||||
|
|
||||||
public enum AutoDeleteAction {
|
public enum AutoDeleteAction {
|
||||||
GLOBAL,
|
GLOBAL,
|
||||||
YES,
|
YES,
|
||||||
|
@ -25,11 +29,16 @@ public class FeedPreferences {
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, String username, String password) {
|
public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, String username, String password) {
|
||||||
|
this(feedID, autoDownload, auto_delete_action, username, password, new FeedFilter());
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, String username, String password, @NonNull FeedFilter filter) {
|
||||||
this.feedID = feedID;
|
this.feedID = feedID;
|
||||||
this.autoDownload = autoDownload;
|
this.autoDownload = autoDownload;
|
||||||
this.auto_delete_action = auto_delete_action;
|
this.auto_delete_action = auto_delete_action;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
|
this.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FeedPreferences fromCursor(Cursor cursor) {
|
public static FeedPreferences fromCursor(Cursor cursor) {
|
||||||
|
@ -38,6 +47,8 @@ public class FeedPreferences {
|
||||||
int indexAutoDeleteAction = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DELETE_ACTION);
|
int indexAutoDeleteAction = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DELETE_ACTION);
|
||||||
int indexUsername = cursor.getColumnIndex(PodDBAdapter.KEY_USERNAME);
|
int indexUsername = cursor.getColumnIndex(PodDBAdapter.KEY_USERNAME);
|
||||||
int indexPassword = cursor.getColumnIndex(PodDBAdapter.KEY_PASSWORD);
|
int indexPassword = cursor.getColumnIndex(PodDBAdapter.KEY_PASSWORD);
|
||||||
|
int indexIncludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_INCLUDE_FILTER);
|
||||||
|
int indexExcludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_EXCLUDE_FILTER);
|
||||||
|
|
||||||
long feedId = cursor.getLong(indexId);
|
long feedId = cursor.getLong(indexId);
|
||||||
boolean autoDownload = cursor.getInt(indexAutoDownload) > 0;
|
boolean autoDownload = cursor.getInt(indexAutoDownload) > 0;
|
||||||
|
@ -45,10 +56,21 @@ public class FeedPreferences {
|
||||||
AutoDeleteAction autoDeleteAction = AutoDeleteAction.values()[autoDeleteActionIndex];
|
AutoDeleteAction autoDeleteAction = AutoDeleteAction.values()[autoDeleteActionIndex];
|
||||||
String username = cursor.getString(indexUsername);
|
String username = cursor.getString(indexUsername);
|
||||||
String password = cursor.getString(indexPassword);
|
String password = cursor.getString(indexPassword);
|
||||||
return new FeedPreferences(feedId, autoDownload, autoDeleteAction, username, password);
|
String includeFilter = cursor.getString(indexIncludeFilter);
|
||||||
|
String excludeFilter = cursor.getString(indexExcludeFilter);
|
||||||
|
return new FeedPreferences(feedId, autoDownload, autoDeleteAction, username, password, new FeedFilter(includeFilter, excludeFilter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the filter for this feed
|
||||||
|
*/
|
||||||
|
public FeedFilter getFilter() {
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilter(@NonNull FeedFilter filter) {
|
||||||
|
this.filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare another FeedPreferences with this one. The feedID, autoDownload and AutoDeleteAction attribute are excluded from the
|
* Compare another FeedPreferences with this one. The feedID, autoDownload and AutoDeleteAction attribute are excluded from the
|
||||||
|
|
|
@ -7,7 +7,9 @@ import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.core.feed.FeedFilter;
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
|
import de.danoeh.antennapod.core.feed.FeedPreferences;
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.core.util.NetworkUtils;
|
import de.danoeh.antennapod.core.util.NetworkUtils;
|
||||||
import de.danoeh.antennapod.core.util.PowerUtils;
|
import de.danoeh.antennapod.core.util.PowerUtils;
|
||||||
|
@ -54,7 +56,9 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
|
||||||
candidates = new ArrayList<FeedItem>(queue.size() + newItems.size());
|
candidates = new ArrayList<FeedItem>(queue.size() + newItems.size());
|
||||||
candidates.addAll(queue);
|
candidates.addAll(queue);
|
||||||
for(FeedItem newItem : newItems) {
|
for(FeedItem newItem : newItems) {
|
||||||
if(candidates.contains(newItem) == false) {
|
FeedPreferences feedPrefs = newItem.getFeed().getPreferences();
|
||||||
|
FeedFilter feedFilter = feedPrefs.getFilter();
|
||||||
|
if(candidates.contains(newItem) == false && feedFilter.shouldAutoDownload(newItem)) {
|
||||||
candidates.add(newItem);
|
candidates.add(newItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,8 @@ public class PodDBAdapter {
|
||||||
public static final String KEY_LAST_UPDATE_FAILED = "last_update_failed";
|
public static final String KEY_LAST_UPDATE_FAILED = "last_update_failed";
|
||||||
public static final String KEY_HAS_EMBEDDED_PICTURE = "has_embedded_picture";
|
public static final String KEY_HAS_EMBEDDED_PICTURE = "has_embedded_picture";
|
||||||
public static final String KEY_LAST_PLAYED_TIME = "last_played_time";
|
public static final String KEY_LAST_PLAYED_TIME = "last_played_time";
|
||||||
|
public static final String KEY_INCLUDE_FILTER = "include_filter";
|
||||||
|
public static final String KEY_EXCLUDE_FILTER = "exclude_filter";
|
||||||
|
|
||||||
// Table names
|
// Table names
|
||||||
public static final String TABLE_NAME_FEEDS = "Feeds";
|
public static final String TABLE_NAME_FEEDS = "Feeds";
|
||||||
|
@ -128,6 +130,8 @@ public class PodDBAdapter {
|
||||||
+ KEY_FLATTR_STATUS + " INTEGER,"
|
+ KEY_FLATTR_STATUS + " INTEGER,"
|
||||||
+ KEY_USERNAME + " TEXT,"
|
+ KEY_USERNAME + " TEXT,"
|
||||||
+ KEY_PASSWORD + " TEXT,"
|
+ KEY_PASSWORD + " TEXT,"
|
||||||
|
+ KEY_INCLUDE_FILTER + " TEXT,"
|
||||||
|
+ KEY_EXCLUDE_FILTER + " TEXT,"
|
||||||
+ KEY_IS_PAGED + " INTEGER DEFAULT 0,"
|
+ KEY_IS_PAGED + " INTEGER DEFAULT 0,"
|
||||||
+ KEY_NEXT_PAGE_LINK + " TEXT,"
|
+ KEY_NEXT_PAGE_LINK + " TEXT,"
|
||||||
+ KEY_HIDE + " TEXT,"
|
+ KEY_HIDE + " TEXT,"
|
||||||
|
@ -238,6 +242,8 @@ public class PodDBAdapter {
|
||||||
TABLE_NAME_FEEDS + "." + KEY_HIDE,
|
TABLE_NAME_FEEDS + "." + KEY_HIDE,
|
||||||
TABLE_NAME_FEEDS + "." + KEY_LAST_UPDATE_FAILED,
|
TABLE_NAME_FEEDS + "." + KEY_LAST_UPDATE_FAILED,
|
||||||
TABLE_NAME_FEEDS + "." + KEY_AUTO_DELETE_ACTION,
|
TABLE_NAME_FEEDS + "." + KEY_AUTO_DELETE_ACTION,
|
||||||
|
TABLE_NAME_FEEDS + "." + KEY_INCLUDE_FILTER,
|
||||||
|
TABLE_NAME_FEEDS + "." + KEY_EXCLUDE_FILTER
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -395,6 +401,8 @@ public class PodDBAdapter {
|
||||||
values.put(KEY_AUTO_DELETE_ACTION,prefs.getAutoDeleteAction().ordinal());
|
values.put(KEY_AUTO_DELETE_ACTION,prefs.getAutoDeleteAction().ordinal());
|
||||||
values.put(KEY_USERNAME, prefs.getUsername());
|
values.put(KEY_USERNAME, prefs.getUsername());
|
||||||
values.put(KEY_PASSWORD, prefs.getPassword());
|
values.put(KEY_PASSWORD, prefs.getPassword());
|
||||||
|
values.put(KEY_INCLUDE_FILTER, prefs.getFilter().getIncludeFilter());
|
||||||
|
values.put(KEY_EXCLUDE_FILTER, prefs.getFilter().getExcludeFilter());
|
||||||
db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())});
|
db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1745,6 +1753,7 @@ public class PodDBAdapter {
|
||||||
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_PUBDATE);
|
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_PUBDATE);
|
||||||
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_READ);
|
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldVersion < 1050003) {
|
if (oldVersion < 1050003) {
|
||||||
// Migrates feed list filter data
|
// Migrates feed list filter data
|
||||||
|
|
||||||
|
@ -1780,6 +1789,13 @@ public class PodDBAdapter {
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
db.endTransaction();
|
db.endTransaction();
|
||||||
|
|
||||||
|
// and now get ready for autodownload filters
|
||||||
|
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
|
||||||
|
+ " ADD COLUMN " + PodDBAdapter.KEY_INCLUDE_FILTER + " TEXT DEFAULT ''");
|
||||||
|
|
||||||
|
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
|
||||||
|
+ " ADD COLUMN " + PodDBAdapter.KEY_EXCLUDE_FILTER + " TEXT DEFAULT ''");
|
||||||
}
|
}
|
||||||
|
|
||||||
EventBus.getDefault().post(ProgressEvent.end());
|
EventBus.getDefault().post(ProgressEvent.end());
|
||||||
|
|
|
@ -530,7 +530,11 @@
|
||||||
<!-- Feed information screen -->
|
<!-- Feed information screen -->
|
||||||
<string name="authentication_label">Authentication</string>
|
<string name="authentication_label">Authentication</string>
|
||||||
<string name="authentication_descr">Change your username and password for this podcast and its episodes.</string>
|
<string name="authentication_descr">Change your username and password for this podcast and its episodes.</string>
|
||||||
|
<string name="episode_filters_label">Episode Filter</string>
|
||||||
|
<string name="episode_filters_description">List of terms used to decide if an episode should be included or excluded from being autodownloaded</string>
|
||||||
|
<string name="episode_filters_include">Include</string>
|
||||||
|
<string name="episode_filters_exclude">Exclude</string>
|
||||||
|
<string name="episode_filters_hint">Filter text</string>
|
||||||
|
|
||||||
<!-- Progress information -->
|
<!-- Progress information -->
|
||||||
<string name="progress_upgrading_database">Upgrading the database</string>
|
<string name="progress_upgrading_database">Upgrading the database</string>
|
||||||
|
|
Loading…
Reference in New Issue