Merge branch 'develop' into 2747-completed-downloads-update
This commit is contained in:
commit
9f6529d4bc
@ -139,6 +139,11 @@ dependencies {
|
|||||||
implementation "com.android.support:gridlayout-v7:$supportVersion"
|
implementation "com.android.support:gridlayout-v7:$supportVersion"
|
||||||
implementation "com.android.support:recyclerview-v7:$supportVersion"
|
implementation "com.android.support:recyclerview-v7:$supportVersion"
|
||||||
compileOnly 'com.google.android.wearable:wearable:2.2.0'
|
compileOnly 'com.google.android.wearable:wearable:2.2.0'
|
||||||
|
|
||||||
|
// ViewModel and LiveData
|
||||||
|
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
|
||||||
|
annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
|
||||||
|
|
||||||
implementation "org.apache.commons:commons-lang3:$commonslangVersion"
|
implementation "org.apache.commons:commons-lang3:$commonslangVersion"
|
||||||
implementation("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") {
|
implementation("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") {
|
||||||
exclude group: "org.json", module: "json"
|
exclude group: "org.json", module: "json"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package de.danoeh.antennapod.activity;
|
package de.danoeh.antennapod.activity;
|
||||||
|
|
||||||
|
import android.arch.lifecycle.ViewModelProviders;
|
||||||
import android.graphics.LightingColorFilter;
|
import android.graphics.LightingColorFilter;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
@ -7,7 +8,6 @@ import android.support.v4.app.FragmentTransaction;
|
|||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
@ -19,10 +19,8 @@ import de.danoeh.antennapod.core.feed.Feed;
|
|||||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||||
import de.danoeh.antennapod.core.glide.FastBlurTransformation;
|
import de.danoeh.antennapod.core.glide.FastBlurTransformation;
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.core.storage.DBReader;
|
|
||||||
import de.danoeh.antennapod.fragment.FeedSettingsFragment;
|
import de.danoeh.antennapod.fragment.FeedSettingsFragment;
|
||||||
import io.reactivex.Maybe;
|
import de.danoeh.antennapod.viewmodel.FeedSettingsViewModel;
|
||||||
import io.reactivex.MaybeOnSubscribe;
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
@ -46,7 +44,6 @@ public class FeedSettingsActivity extends AppCompatActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.feedsettings);
|
setContentView(R.layout.feedsettings);
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1);
|
|
||||||
|
|
||||||
imgvCover = findViewById(R.id.imgvCover);
|
imgvCover = findViewById(R.id.imgvCover);
|
||||||
txtvTitle = findViewById(R.id.txtvTitle);
|
txtvTitle = findViewById(R.id.txtvTitle);
|
||||||
@ -57,14 +54,8 @@ public class FeedSettingsActivity extends AppCompatActivity {
|
|||||||
// https://github.com/bumptech/glide/issues/529
|
// https://github.com/bumptech/glide/issues/529
|
||||||
imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
|
imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
|
||||||
|
|
||||||
disposable = Maybe.create((MaybeOnSubscribe<Feed>) emitter -> {
|
long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1);
|
||||||
Feed feed = DBReader.getFeed(feedId);
|
disposable = ViewModelProviders.of(this).get(FeedSettingsViewModel.class).getFeed(feedId)
|
||||||
if (feed != null) {
|
|
||||||
emitter.onSuccess(feed);
|
|
||||||
} else {
|
|
||||||
emitter.onComplete();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(result -> {
|
.subscribe(result -> {
|
||||||
@ -91,10 +82,6 @@ public class FeedSettingsActivity extends AppCompatActivity {
|
|||||||
fragmentTransaction.commit();
|
fragmentTransaction.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Feed getFeed() {
|
|
||||||
return feed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showHeader() {
|
private void showHeader() {
|
||||||
txtvTitle.setText(feed.getTitle());
|
txtvTitle.setText(feed.getTitle());
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ import android.widget.ViewFlipper;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import de.danoeh.antennapod.BuildConfig;
|
import de.danoeh.antennapod.BuildConfig;
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
@ -123,6 +125,11 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity {
|
|||||||
final String usernameStr = username.getText().toString();
|
final String usernameStr = username.getText().toString();
|
||||||
final String passwordStr = password.getText().toString();
|
final String passwordStr = password.getText().toString();
|
||||||
|
|
||||||
|
if (usernameHasUnwantedChars(usernameStr)) {
|
||||||
|
txtvError.setText(R.string.gpodnetsync_username_characters_error);
|
||||||
|
txtvError.setVisibility(View.VISIBLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (BuildConfig.DEBUG) Log.d(TAG, "Checking login credentials");
|
if (BuildConfig.DEBUG) Log.d(TAG, "Checking login credentials");
|
||||||
AsyncTask<GpodnetService, Void, Void> authTask = new AsyncTask<GpodnetService, Void, Void>() {
|
AsyncTask<GpodnetService, Void, Void> authTask = new AsyncTask<GpodnetService, Void, Void>() {
|
||||||
|
|
||||||
@ -395,4 +402,10 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity {
|
|||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean usernameHasUnwantedChars(String username) {
|
||||||
|
Pattern special = Pattern.compile("[!@#$%&*()+=|<>?{}\\[\\]~]");
|
||||||
|
Matcher containsUnwantedChars = special.matcher(username);
|
||||||
|
return containsUnwantedChars.find();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,6 +258,9 @@ public class AllEpisodesFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem item) {
|
public boolean onContextItemSelected(MenuItem item) {
|
||||||
Log.d(TAG, "onContextItemSelected() called with: " + "item = [" + item + "]");
|
Log.d(TAG, "onContextItemSelected() called with: " + "item = [" + item + "]");
|
||||||
|
if (!getUserVisibleHint()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!isVisible()) {
|
if (!isVisible()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ public class CoverFragment extends Fragment {
|
|||||||
txtvPodcastTitle = root.findViewById(R.id.txtvPodcastTitle);
|
txtvPodcastTitle = root.findViewById(R.id.txtvPodcastTitle);
|
||||||
txtvEpisodeTitle = root.findViewById(R.id.txtvEpisodeTitle);
|
txtvEpisodeTitle = root.findViewById(R.id.txtvEpisodeTitle);
|
||||||
imgvCover = root.findViewById(R.id.imgvCover);
|
imgvCover = root.findViewById(R.id.imgvCover);
|
||||||
|
imgvCover.setOnClickListener(v -> onPlayPause());
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,4 +115,11 @@ public class CoverFragment extends Fragment {
|
|||||||
disposable.dispose();
|
disposable.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onPlayPause() {
|
||||||
|
if (controller == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
controller.playPause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package de.danoeh.antennapod.fragment;
|
package de.danoeh.antennapod.fragment;
|
||||||
|
|
||||||
|
import android.arch.lifecycle.ViewModelProviders;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -7,7 +8,6 @@ import android.support.v14.preference.SwitchPreference;
|
|||||||
import android.support.v7.preference.ListPreference;
|
import android.support.v7.preference.ListPreference;
|
||||||
import android.support.v7.preference.PreferenceFragmentCompat;
|
import android.support.v7.preference.PreferenceFragmentCompat;
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.activity.FeedSettingsActivity;
|
|
||||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||||
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.FeedFilter;
|
||||||
@ -16,6 +16,9 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
|
|||||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||||
import de.danoeh.antennapod.dialog.AuthenticationDialog;
|
import de.danoeh.antennapod.dialog.AuthenticationDialog;
|
||||||
import de.danoeh.antennapod.dialog.EpisodeFilterDialog;
|
import de.danoeh.antennapod.dialog.EpisodeFilterDialog;
|
||||||
|
import de.danoeh.antennapod.viewmodel.FeedSettingsViewModel;
|
||||||
|
|
||||||
|
import static de.danoeh.antennapod.activity.FeedSettingsActivity.EXTRA_FEED_ID;
|
||||||
|
|
||||||
public class FeedSettingsFragment extends PreferenceFragmentCompat {
|
public class FeedSettingsFragment extends PreferenceFragmentCompat {
|
||||||
private static final CharSequence PREF_EPISODE_FILTER = "episodeFilter";
|
private static final CharSequence PREF_EPISODE_FILTER = "episodeFilter";
|
||||||
@ -26,17 +29,21 @@ public class FeedSettingsFragment extends PreferenceFragmentCompat {
|
|||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
addPreferencesFromResource(R.xml.feed_settings);
|
addPreferencesFromResource(R.xml.feed_settings);
|
||||||
|
|
||||||
feed = ((FeedSettingsActivity) getActivity()).getFeed();
|
long feedId = getArguments().getLong(EXTRA_FEED_ID);
|
||||||
feedPreferences = feed.getPreferences();
|
ViewModelProviders.of(getActivity()).get(FeedSettingsViewModel.class).getFeed(feedId)
|
||||||
|
.subscribe(result -> {
|
||||||
|
feed = result;
|
||||||
|
feedPreferences = feed.getPreferences();
|
||||||
|
|
||||||
setupAutoDownloadPreference();
|
setupAutoDownloadPreference();
|
||||||
setupKeepUpdatedPreference();
|
setupKeepUpdatedPreference();
|
||||||
setupAutoDeletePreference();
|
setupAutoDeletePreference();
|
||||||
setupAuthentificationPreference();
|
setupAuthentificationPreference();
|
||||||
setupEpisodeFilterPreference();
|
setupEpisodeFilterPreference();
|
||||||
|
|
||||||
updateAutoDeleteSummary();
|
updateAutoDeleteSummary();
|
||||||
updateAutoDownloadEnabled();
|
updateAutoDownloadEnabled();
|
||||||
|
}).dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupEpisodeFilterPreference() {
|
private void setupEpisodeFilterPreference() {
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package de.danoeh.antennapod.viewmodel;
|
||||||
|
|
||||||
|
import android.arch.lifecycle.ViewModel;
|
||||||
|
import de.danoeh.antennapod.core.feed.Feed;
|
||||||
|
import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
|
import io.reactivex.Maybe;
|
||||||
|
|
||||||
|
public class FeedSettingsViewModel extends ViewModel {
|
||||||
|
private Feed feed;
|
||||||
|
|
||||||
|
public Maybe<Feed> getFeed(long feedId) {
|
||||||
|
if (feed == null) {
|
||||||
|
return loadFeed(feedId);
|
||||||
|
} else {
|
||||||
|
return Maybe.just(feed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Maybe<Feed> loadFeed(long feedId) {
|
||||||
|
return Maybe.create(emitter -> {
|
||||||
|
Feed feed = DBReader.getFeed(feedId);
|
||||||
|
if (feed != null) {
|
||||||
|
this.feed = feed;
|
||||||
|
emitter.onSuccess(feed);
|
||||||
|
} else {
|
||||||
|
emitter.onComplete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -26,7 +26,8 @@
|
|||||||
android:contentDescription="@string/cover_label"
|
android:contentDescription="@string/cover_label"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:transitionName="coverTransition"
|
android:transitionName="coverTransition"
|
||||||
tools:src="@android:drawable/sym_def_app_icon" />
|
tools:src="@android:drawable/sym_def_app_icon"
|
||||||
|
android:foreground="?attr/selectableItemBackground" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtvEpisodeTitle"
|
android:id="@+id/txtvEpisodeTitle"
|
||||||
|
@ -45,6 +45,7 @@ project.ext {
|
|||||||
targetSdkVersion = 26
|
targetSdkVersion = 26
|
||||||
|
|
||||||
supportVersion = "27.1.1"
|
supportVersion = "27.1.1"
|
||||||
|
lifecycle_version = "1.1.1"
|
||||||
workManagerVersion = "1.0.1"
|
workManagerVersion = "1.0.1"
|
||||||
awaitilityVersion = "3.1.2"
|
awaitilityVersion = "3.1.2"
|
||||||
commonsioVersion = "2.5"
|
commonsioVersion = "2.5"
|
||||||
|
@ -7,6 +7,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
|
|
||||||
import java.text.ParsePosition;
|
import java.text.ParsePosition;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -162,11 +163,10 @@ public class DateUtils {
|
|||||||
if (date == null) {
|
if (date == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
GregorianCalendar now = new GregorianCalendar();
|
||||||
GregorianCalendar cal = new GregorianCalendar();
|
GregorianCalendar cal = new GregorianCalendar();
|
||||||
cal.add(GregorianCalendar.YEAR, -1);
|
cal.setTime(date);
|
||||||
// some padding, because no one really remembers what day of the month it is
|
boolean withinLastYear = now.get(Calendar.YEAR) == cal.get(Calendar.YEAR);
|
||||||
cal.add(GregorianCalendar.DAY_OF_MONTH, 10);
|
|
||||||
boolean withinLastYear = date.after(cal.getTime());
|
|
||||||
int format = android.text.format.DateUtils.FORMAT_ABBREV_ALL;
|
int format = android.text.format.DateUtils.FORMAT_ABBREV_ALL;
|
||||||
if (withinLastYear) {
|
if (withinLastYear) {
|
||||||
format |= android.text.format.DateUtils.FORMAT_NO_YEAR;
|
format |= android.text.format.DateUtils.FORMAT_NO_YEAR;
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package de.danoeh.antennapod.core.util.id3reader;
|
package de.danoeh.antennapod.core.util.id3reader;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import de.danoeh.antennapod.core.feed.Chapter;
|
||||||
|
import de.danoeh.antennapod.core.feed.ID3Chapter;
|
||||||
|
import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader;
|
||||||
|
import de.danoeh.antennapod.core.util.id3reader.model.TagHeader;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -8,11 +12,6 @@ import java.net.URLDecoder;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.danoeh.antennapod.core.feed.Chapter;
|
|
||||||
import de.danoeh.antennapod.core.feed.ID3Chapter;
|
|
||||||
import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader;
|
|
||||||
import de.danoeh.antennapod.core.util.id3reader.model.TagHeader;
|
|
||||||
|
|
||||||
public class ChapterReader extends ID3Reader {
|
public class ChapterReader extends ID3Reader {
|
||||||
private static final String TAG = "ID3ChapterReader";
|
private static final String TAG = "ID3ChapterReader";
|
||||||
|
|
||||||
@ -69,11 +68,14 @@ public class ChapterReader extends ID3Reader {
|
|||||||
int descriptionLength = readString(null, input, header.getSize());
|
int descriptionLength = readString(null, input, header.getSize());
|
||||||
StringBuilder link = new StringBuilder();
|
StringBuilder link = new StringBuilder();
|
||||||
readISOString(link, input, header.getSize() - descriptionLength);
|
readISOString(link, input, header.getSize() - descriptionLength);
|
||||||
String decodedLink = URLDecoder.decode(link.toString(), "UTF-8");
|
try {
|
||||||
|
String decodedLink = URLDecoder.decode(link.toString(), "UTF-8");
|
||||||
|
currentChapter.setLink(decodedLink);
|
||||||
|
Log.d(TAG, "Found link: " + currentChapter.getLink());
|
||||||
|
} catch (IllegalArgumentException _iae) {
|
||||||
|
Log.w(TAG, "Bad URL found in ID3 data");
|
||||||
|
}
|
||||||
|
|
||||||
currentChapter.setLink(decodedLink);
|
|
||||||
|
|
||||||
Log.d(TAG, "Found link: " + currentChapter.getLink());
|
|
||||||
return ID3Reader.ACTION_DONT_SKIP;
|
return ID3Reader.ACTION_DONT_SKIP;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -642,6 +642,7 @@
|
|||||||
<string name="gpodnetsync_error_descr">An error occurred during syncing:\u0020</string>
|
<string name="gpodnetsync_error_descr">An error occurred during syncing:\u0020</string>
|
||||||
<string name="gpodnetsync_pref_report_successful">Successful</string>
|
<string name="gpodnetsync_pref_report_successful">Successful</string>
|
||||||
<string name="gpodnetsync_pref_report_failed">Failed</string>
|
<string name="gpodnetsync_pref_report_failed">Failed</string>
|
||||||
|
<string name="gpodnetsync_username_characters_error">Usernames may only contain letters, digits, hyphens and underscores.</string>
|
||||||
|
|
||||||
<!-- Directory chooser -->
|
<!-- Directory chooser -->
|
||||||
<string name="selected_folder_label">Selected folder:</string>
|
<string name="selected_folder_label">Selected folder:</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user