summaryrefslogtreecommitdiff
path: root/app/src/main/java/de
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/de')
-rw-r--r--app/src/main/java/de/danoeh/antennapod/PodcastApp.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java11
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/CastEnabledActivity.java237
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java183
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java68
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java215
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java40
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java101
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java17
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java23
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java16
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java23
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java74
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java14
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java47
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java11
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java44
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java80
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java65
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java122
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java15
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java17
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java44
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java57
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java56
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java16
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java21
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java24
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java192
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java22
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java20
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java69
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java19
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java18
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java39
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java235
69 files changed, 1427 insertions, 1004 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
index f6a8db5fb..caa82d725 100644
--- a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
+++ b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
@@ -3,6 +3,7 @@ package de.danoeh.antennapod;
import android.app.Application;
import android.os.Build;
import android.os.StrictMode;
+import android.support.multidex.MultiDexApplication;
import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.fonts.FontAwesomeModule;
@@ -13,7 +14,7 @@ import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.spa.SPAUtil;
/** Main application class. */
-public class PodcastApp extends Application {
+public class PodcastApp extends MultiDexApplication {
// make sure that ClientConfigurator executes its static code
static {
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java
index eef2fa4da..1b42b274c 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java
@@ -124,12 +124,11 @@ public class AboutActivity extends AppCompatActivity {
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(webviewData -> {
- webview.loadDataWithBaseURL("file:///android_asset/", webviewData, "text/html",
- "utf-8", "about:blank");
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ .subscribe(
+ webviewData ->
+ webview.loadDataWithBaseURL("file:///android_asset/", webviewData, "text/html", "utf-8", "about:blank"),
+ error -> Log.e(TAG, Log.getStackTraceString(error))
+ );
}
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/CastEnabledActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
deleted file mode 100644
index b8856c295..000000000
--- a/app/src/main/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
+++ /dev/null
@@ -1,237 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.content.SharedPreferences;
-import android.media.AudioManager;
-import android.os.Bundle;
-import android.preference.PreferenceManager;
-import android.support.annotation.CallSuper;
-import android.support.v4.view.MenuItemCompat;
-import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-
-import com.google.android.gms.cast.ApplicationMetadata;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.cast.CastConsumer;
-import de.danoeh.antennapod.core.cast.CastManager;
-import de.danoeh.antennapod.core.cast.DefaultCastConsumer;
-import de.danoeh.antennapod.core.cast.SwitchableMediaRouteActionProvider;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.service.playback.PlaybackService;
-
-/**
- * Activity that allows for showing the MediaRouter button whenever there's a cast device in the
- * network.
- */
-public abstract class CastEnabledActivity extends AppCompatActivity
- implements SharedPreferences.OnSharedPreferenceChangeListener {
- public static final String TAG = "CastEnabledActivity";
-
- protected CastManager castManager;
- protected SwitchableMediaRouteActionProvider mediaRouteActionProvider;
- private final CastButtonVisibilityManager castButtonVisibilityManager = new CastButtonVisibilityManager();
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).
- registerOnSharedPreferenceChangeListener(this);
-
- castManager = CastManager.getInstance();
- castManager.addCastConsumer(castConsumer);
- castButtonVisibilityManager.setPrefEnabled(UserPreferences.isCastEnabled());
- onCastConnectionChanged(castManager.isConnected());
- }
-
- @Override
- protected void onDestroy() {
- PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
- .unregisterOnSharedPreferenceChangeListener(this);
- castManager.removeCastConsumer(castConsumer);
- super.onDestroy();
- }
-
- @Override
- @CallSuper
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- getMenuInflater().inflate(R.menu.cast_enabled, menu);
- castButtonVisibilityManager.setMenu(menu);
- return true;
- }
-
- @Override
- @CallSuper
- public boolean onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
- mediaRouteActionProvider = castManager
- .addMediaRouterButton(menu.findItem(R.id.media_route_menu_item));
- mediaRouteActionProvider.setEnabled(castButtonVisibilityManager.shouldEnable());
- return true;
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- castButtonVisibilityManager.setResumed(true);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- castButtonVisibilityManager.setResumed(false);
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if (UserPreferences.PREF_CAST_ENABLED.equals(key)) {
- boolean newValue = UserPreferences.isCastEnabled();
- Log.d(TAG, "onSharedPreferenceChanged(), isCastEnabled set to " + newValue);
- castButtonVisibilityManager.setPrefEnabled(newValue);
- // PlaybackService has its own listener, so if it's active we don't have to take action here.
- if (!newValue && !PlaybackService.isRunning) {
- CastManager.getInstance().disconnect();
- }
- }
- }
-
- CastConsumer castConsumer = new DefaultCastConsumer() {
- @Override
- public void onApplicationConnected(ApplicationMetadata appMetadata, String sessionId, boolean wasLaunched) {
- onCastConnectionChanged(true);
- }
-
- @Override
- public void onDisconnected() {
- onCastConnectionChanged(false);
- }
- };
-
- private void onCastConnectionChanged(boolean connected) {
- if (connected) {
- castButtonVisibilityManager.onConnected();
- setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE);
- } else {
- castButtonVisibilityManager.onDisconnected();
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
- }
- }
-
- /**
- * Should be called by any activity or fragment for which the cast button should be shown.
- *
- * @param showAsAction refer to {@link MenuItem#setShowAsAction(int)}
- */
- public final void requestCastButton(int showAsAction) {
- castButtonVisibilityManager.requestCastButton(showAsAction);
- }
-
- private class CastButtonVisibilityManager {
- private volatile boolean prefEnabled = false;
- private volatile boolean viewRequested = false;
- private volatile boolean resumed = false;
- private volatile boolean connected = false;
- private volatile int showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
- private Menu menu;
-
- public synchronized void setPrefEnabled(boolean newValue) {
- if (prefEnabled != newValue && resumed && (viewRequested || connected)) {
- if (newValue) {
- castManager.incrementUiCounter();
- } else {
- castManager.decrementUiCounter();
- }
- }
- prefEnabled = newValue;
- if (mediaRouteActionProvider != null) {
- mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
- }
- }
-
- public synchronized void setResumed(boolean newValue) {
- if (resumed == newValue) {
- Log.e(TAG, "resumed should never change to the same value");
- return;
- }
- resumed = newValue;
- if (prefEnabled && (viewRequested || connected)) {
- if (resumed) {
- castManager.incrementUiCounter();
- } else {
- castManager.decrementUiCounter();
- }
- }
- }
-
- public synchronized void setViewRequested(boolean newValue) {
- if (viewRequested != newValue && resumed && prefEnabled && !connected) {
- if (newValue) {
- castManager.incrementUiCounter();
- } else {
- castManager.decrementUiCounter();
- }
- }
- viewRequested = newValue;
- if (mediaRouteActionProvider != null) {
- mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
- }
- }
-
- public synchronized void setConnected(boolean newValue) {
- if (connected != newValue && resumed && prefEnabled && !prefEnabled) {
- if (newValue) {
- castManager.incrementUiCounter();
- } else {
- castManager.decrementUiCounter();
- }
- }
- connected = newValue;
- if (mediaRouteActionProvider != null) {
- mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
- }
- }
-
- public synchronized boolean shouldEnable() {
- return prefEnabled && viewRequested;
- }
-
- public void setMenu(Menu menu) {
- setViewRequested(false);
- showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
- this.menu = menu;
- setShowAsAction();
- }
-
- public void requestCastButton(int showAsAction) {
- setViewRequested(true);
- this.showAsAction = showAsAction;
- setShowAsAction();
- }
-
- public void onConnected() {
- setConnected(true);
- setShowAsAction();
- }
-
- public void onDisconnected() {
- setConnected(false);
- setShowAsAction();
- }
-
- private void setShowAsAction() {
- if (menu == null) {
- Log.d(TAG, "setShowAsAction() without a menu");
- return;
- }
- MenuItem item = menu.findItem(R.id.media_route_menu_item);
- if (item == null) {
- Log.e(TAG, "setShowAsAction(), but cast button not inflated");
- return;
- }
- MenuItemCompat.setShowAsAction(item, connected? MenuItem.SHOW_AS_ACTION_ALWAYS : showAsAction);
- }
- }
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java
index 1ca4d095f..a7e9b1e70 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java
@@ -50,10 +50,10 @@ public class CastplayerActivity extends MediaplayerInfoActivity {
if (butPlaybackSpeed != null) {
butPlaybackSpeed.setVisibility(View.GONE);
}
- if (butCastDisconnect != null) {
- butCastDisconnect.setOnClickListener(v -> castManager.disconnect());
- butCastDisconnect.setVisibility(View.VISIBLE);
- }
+// if (butCastDisconnect != null) {
+// butCastDisconnect.setOnClickListener(v -> castManager.disconnect());
+// butCastDisconnect.setVisibility(View.VISIBLE);
+// }
}
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java
index 5fd69ef6a..390d4cef8 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java
@@ -89,9 +89,7 @@ public class DirectoryChooserActivity extends AppCompatActivity {
adb.setTitle(R.string.folder_not_empty_dialog_title);
adb.setMessage(R.string.folder_not_empty_dialog_msg);
adb.setNegativeButton(R.string.cancel_label,
- (dialog, which) -> {
- dialog.dismiss();
- });
+ (dialog, which) -> dialog.dismiss());
adb.setPositiveButton(R.string.confirm_label,
(dialog, which) -> {
dialog.dismiss();
@@ -291,9 +289,7 @@ public class DirectoryChooserActivity extends AppCompatActivity {
builder.setMessage(String.format(getString(R.string.create_folder_msg),
CREATE_DIRECTORY_NAME));
builder.setNegativeButton(R.string.cancel_label,
- (dialog, which) -> {
- dialog.dismiss();
- });
+ (dialog, which) -> dialog.dismiss());
builder.setPositiveButton(R.string.confirm_label,
(dialog, which) -> {
dialog.dismiss();
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java
index d4356719e..2a58d5104 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java
@@ -5,10 +5,10 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
+import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
@@ -28,6 +28,10 @@ import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.joanzapata.iconify.Iconify;
+import org.apache.commons.lang3.StringUtils;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
@@ -41,23 +45,29 @@ import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.LangUtils;
+import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
+import rx.Observable;
+import rx.Subscription;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
/**
* Displays information about a feed.
*/
-public class FeedInfoActivity extends ActionBarActivity {
- private static final String TAG = "FeedInfoActivity";
- private boolean autoDeleteChanged = false;
+public class FeedInfoActivity extends AppCompatActivity {
public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
-
+ private static final String TAG = "FeedInfoActivity";
+ private boolean autoDeleteChanged = false;
private Feed feed;
private ImageView imgvCover;
private TextView txtvTitle;
private TextView txtvDescription;
+ private TextView lblLanguage;
private TextView txtvLanguage;
+ private TextView lblAuthor;
private TextView txtvAuthor;
private TextView txtvUrl;
private EditText etxtUsername;
@@ -70,6 +80,9 @@ public class FeedInfoActivity extends ActionBarActivity {
private Spinner spnAutoDelete;
private boolean filterInclude = true;
+ private Subscription subscription;
+
+
private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -91,6 +104,40 @@ public class FeedInfoActivity extends ActionBarActivity {
}
};
+ private boolean authInfoChanged = false;
+
+ private TextWatcher authTextWatcher = 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) {
+ authInfoChanged = true;
+ }
+ };
+
+ 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
protected void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
@@ -102,7 +149,9 @@ public class FeedInfoActivity extends ActionBarActivity {
imgvCover = (ImageView) findViewById(R.id.imgvCover);
txtvTitle = (TextView) findViewById(R.id.txtvTitle);
txtvDescription = (TextView) findViewById(R.id.txtvDescription);
+ lblLanguage = (TextView) findViewById(R.id.lblLanguage);
txtvLanguage = (TextView) findViewById(R.id.txtvLanguage);
+ lblAuthor = (TextView) findViewById(R.id.lblAuthor);
txtvAuthor = (TextView) findViewById(R.id.txtvAuthor);
txtvUrl = (TextView) findViewById(R.id.txtvUrl);
cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload);
@@ -124,48 +173,62 @@ public class FeedInfoActivity extends ActionBarActivity {
txtvUrl.setOnClickListener(copyUrlToClipboard);
- AsyncTask<Long, Void, Feed> loadTask = new AsyncTask<Long, Void, Feed>() {
-
- @Override
- protected Feed doInBackground(Long... params) {
- return DBReader.getFeed(params[0]);
- }
-
- @Override
- protected void onPostExecute(Feed result) {
- if (result != null) {
+ subscription = Observable.fromCallable(()-> DBReader.getFeed(feedId))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> {
+ if (result == null) {
+ Log.e(TAG, "Activity was started with invalid arguments");
+ finish();
+ }
feed = result;
Log.d(TAG, "Language is " + feed.getLanguage());
Log.d(TAG, "Author is " + feed.getAuthor());
Log.d(TAG, "URL is " + feed.getDownload_url());
FeedPreferences prefs = feed.getPreferences();
- imgvCover.post(() -> Glide.with(FeedInfoActivity.this)
- .load(feed.getImageUri())
+ Glide.with(FeedInfoActivity.this)
+ .load(feed.getImageLocation())
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
.dontAnimate()
- .into(imgvCover));
+ .into(imgvCover);
txtvTitle.setText(feed.getTitle());
+
String description = feed.getDescription();
- txtvDescription.setText((description != null) ? description.trim() : "");
- if (feed.getAuthor() != null) {
+ if(description != null) {
+ if(Feed.TYPE_ATOM1.equals(feed.getType())) {
+ HtmlToPlainText formatter = new HtmlToPlainText();
+ Document feedDescription = Jsoup.parse(feed.getDescription());
+ description = StringUtils.trim(formatter.getPlainText(feedDescription));
+ }
+ } else {
+ description = "";
+ }
+ txtvDescription.setText(description);
+
+ if (!TextUtils.isEmpty(feed.getAuthor())) {
txtvAuthor.setText(feed.getAuthor());
+ } else {
+ lblAuthor.setVisibility(View.GONE);
+ txtvAuthor.setVisibility(View.GONE);
}
- if (feed.getLanguage() != null) {
- txtvLanguage.setText(LangUtils
- .getLanguageString(feed.getLanguage()));
+ if (!TextUtils.isEmpty(feed.getLanguage())) {
+ txtvLanguage.setText(LangUtils.getLanguageString(feed.getLanguage()));
+ } else {
+ lblLanguage.setVisibility(View.GONE);
+ txtvLanguage.setVisibility(View.GONE);
}
txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}");
- Iconify.addIcons(txtvUrl);
+ Iconify.addIcons(txtvUrl);
cbxAutoDownload.setEnabled(UserPreferences.isEnableAutodownload());
cbxAutoDownload.setChecked(prefs.getAutoDownload());
cbxAutoDownload.setOnCheckedChangeListener((compoundButton, checked) -> {
feed.getPreferences().setAutoDownload(checked);
- feed.savePreferences(FeedInfoActivity.this);
+ feed.savePreferences();
updateAutoDownloadSettings();
ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(FeedInfoActivity.this,
feed, checked);
@@ -174,7 +237,7 @@ public class FeedInfoActivity extends ActionBarActivity {
cbxKeepUpdated.setChecked(prefs.getKeepUpdated());
cbxKeepUpdated.setOnCheckedChangeListener((compoundButton, checked) -> {
feed.getPreferences().setKeepUpdated(checked);
- feed.savePreferences(FeedInfoActivity.this);
+ feed.savePreferences();
});
spnAutoDelete.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
@@ -184,15 +247,12 @@ public class FeedInfoActivity extends ActionBarActivity {
case 0:
auto_delete_action = FeedPreferences.AutoDeleteAction.GLOBAL;
break;
-
case 1:
auto_delete_action = FeedPreferences.AutoDeleteAction.YES;
break;
-
case 2:
auto_delete_action = FeedPreferences.AutoDeleteAction.NO;
break;
-
default: // TODO - add exceptions here
return;
}
@@ -234,57 +294,12 @@ public class FeedInfoActivity extends ActionBarActivity {
supportInvalidateOptionsMenu();
updateAutoDownloadSettings();
- } else {
- Log.e(TAG, "Activity was started with invalid arguments");
- }
- }
- };
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- loadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, feedId);
- } else {
- loadTask.execute(feedId);
- }
+ }, error -> {
+ Log.d(TAG, Log.getStackTraceString(error));
+ finish();
+ });
}
-
- private boolean authInfoChanged = false;
-
- private TextWatcher authTextWatcher = 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) {
- authInfoChanged = true;
- }
- };
-
- 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
protected void onPause() {
super.onPause();
@@ -317,6 +332,14 @@ public class FeedInfoActivity extends ActionBarActivity {
}
@Override
+ public void onDestroy() {
+ super.onDestroy();
+ if(subscription != null) {
+ subscription.unsubscribe();
+ }
+ }
+
+ @Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
@@ -367,7 +390,7 @@ public class FeedInfoActivity extends ActionBarActivity {
private final Feed feed;
private final boolean autoDownload;
- public ApplyToEpisodesDialog(Context context, Feed feed, boolean autoDownload) {
+ ApplyToEpisodesDialog(Context context, Feed feed, boolean autoDownload) {
super(context, R.string.auto_download_apply_to_items_title,
R.string.auto_download_apply_to_items_message);
this.feed = feed;
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
index b7c7d86c7..f0fcdca90 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
@@ -10,6 +10,7 @@ import android.database.DataSetObserver;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
@@ -38,6 +39,7 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.NavListAdapter;
import de.danoeh.antennapod.core.asynctask.FeedRemover;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.event.MessageEvent;
import de.danoeh.antennapod.core.event.ProgressEvent;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
@@ -46,10 +48,13 @@ import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.core.util.Flavors;
import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.dialog.RatingDialog;
+import de.danoeh.antennapod.dialog.RenameFeedDialog;
import de.danoeh.antennapod.fragment.AddFeedFragment;
import de.danoeh.antennapod.fragment.DownloadsFragment;
import de.danoeh.antennapod.fragment.EpisodesFragment;
@@ -148,9 +153,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
final FragmentManager fm = getSupportFragmentManager();
- fm.addOnBackStackChangedListener(() -> {
- drawerToggle.setDrawerIndicatorEnabled(fm.getBackStackEntryCount() == 0);
- });
+ fm.addOnBackStackChangedListener(() -> drawerToggle.setDrawerIndicatorEnabled(fm.getBackStackEntryCount() == 0));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
@@ -209,7 +212,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
} else {
edit.remove(PREF_LAST_FRAGMENT_TAG);
}
- edit.commit();
+ edit.apply();
}
private String getLastNavFragment() {
@@ -254,9 +257,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]);
}
});
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- UserPreferences.setHiddenDrawerItems(hiddenDrawerItems);
- });
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> UserPreferences.setHiddenDrawerItems(hiddenDrawerItems));
builder.setNegativeButton(R.string.cancel_label, null);
builder.create().show();
}
@@ -466,6 +467,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
protected void onResume() {
super.onResume();
StorageUtils.checkStorageAvailability(this);
+ DBTasks.checkShouldRefreshFeeds(getApplicationContext());
Intent intent = getIntent();
if (intent.hasExtra(EXTRA_FEED_ID) ||
@@ -507,21 +509,24 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
@Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean retVal = super.onCreateOptionsMenu(menu);
- switch (getLastNavFragment()) {
- case QueueFragment.TAG:
- case EpisodesFragment.TAG:
- requestCastButton(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- return retVal;
- case DownloadsFragment.TAG:
- case PlaybackHistoryFragment.TAG:
- case AddFeedFragment.TAG:
- case SubscriptionFragment.TAG:
- return retVal;
- default:
- requestCastButton(MenuItem.SHOW_AS_ACTION_NEVER);
- return retVal;
+ if (Flavors.FLAVOR == Flavors.PLAY) {
+ switch (getLastNavFragment()) {
+ case QueueFragment.TAG:
+ case EpisodesFragment.TAG:
+ requestCastButton(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ return retVal;
+ case DownloadsFragment.TAG:
+ case PlaybackHistoryFragment.TAG:
+ case AddFeedFragment.TAG:
+ case SubscriptionFragment.TAG:
+ return retVal;
+ default:
+ requestCastButton(MenuItem.SHOW_AS_ACTION_NEVER);
+ return retVal;
+ }
+ } else {
+ return retVal;
}
-
}
@Override
@@ -573,6 +578,9 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
case R.id.mark_all_read_item:
DBWriter.markFeedRead(feed.getId());
return true;
+ case R.id.rename_item:
+ new RenameFeedDialog(this, feed).show();
+ return true;
case R.id.remove_item:
final FeedRemover remover = new FeedRemover(this, feed) {
@Override
@@ -585,7 +593,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
};
ConfirmationDialog conDialog = new ConfirmationDialog(this,
R.string.remove_feed_label,
- R.string.feed_delete_confirmation_msg) {
+ getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
@Override
public void onConfirmButtonPressed(
DialogInterface dialog) {
@@ -699,9 +707,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
if (handleIntent) {
handleNavIntent();
}
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
public void onEvent(QueueEvent event) {
@@ -733,6 +739,18 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
}
}
+ public void onEventMainThread(MessageEvent event) {
+ Log.d(TAG, "onEvent(" + event + ")");
+ View parentLayout = findViewById(R.id.drawer_layout);
+ Snackbar snackbar = Snackbar.make(parentLayout, event.message, Snackbar.LENGTH_SHORT);
+ if(event.action != null) {
+ snackbar.setAction(getString(R.string.undo), v -> {
+ event.action.run();
+ });
+ }
+ snackbar.show();
+ }
+
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
index 71d288725..21a0fa66f 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
@@ -1,6 +1,7 @@
package de.danoeh.antennapod.activity;
import android.annotation.TargetApi;
+import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
@@ -9,6 +10,7 @@ import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
+import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.Menu;
@@ -39,8 +41,10 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.Flavors;
import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.StorageUtils;
+import de.danoeh.antennapod.core.util.Supplier;
import de.danoeh.antennapod.core.util.playback.MediaPlayerError;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
@@ -48,6 +52,8 @@ import de.danoeh.antennapod.dialog.SleepTimerDialog;
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
+import rx.functions.Action1;
+import rx.functions.Func1;
import rx.schedulers.Schedulers;
@@ -177,6 +183,13 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
};
}
+ protected static TextView getTxtvFFFromActivity(MediaplayerActivity activity) {
+ return activity.txtvFF;
+ }
+ protected static TextView getTxtvRevFromActivity(MediaplayerActivity activity) {
+ return activity.txtvRev;
+ }
+
protected void onSetSpeedAbilityChanged() {
Log.d(TAG, "onSetSpeedAbilityChanged()");
updatePlaybackSpeedButton();
@@ -281,7 +294,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
- requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ if (Flavors.FLAVOR == Flavors.PLAY) {
+ requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ }
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mediaplayer, menu);
return true;
@@ -294,10 +309,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
return false;
}
Playable media = controller.getMedia();
+ boolean isFeedMedia = media != null && (media instanceof FeedMedia);
- menu.findItem(R.id.support_item).setVisible(
- media != null && media.getPaymentLink() != null &&
- (media instanceof FeedMedia) &&
+ menu.findItem(R.id.support_item).setVisible(isFeedMedia && media.getPaymentLink() != null &&
((FeedMedia) media).getItem() != null &&
((FeedMedia) media).getItem().getFlattrStatus().flattrable()
);
@@ -305,20 +319,21 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
boolean hasWebsiteLink = media != null && media.getWebsiteLink() != null;
menu.findItem(R.id.visit_website_item).setVisible(hasWebsiteLink);
- boolean isItemAndHasLink = media != null && (media instanceof FeedMedia) &&
+ boolean isItemAndHasLink = isFeedMedia &&
((FeedMedia) media).getItem() != null && ((FeedMedia) media).getItem().getLink() != null;
menu.findItem(R.id.share_link_item).setVisible(isItemAndHasLink);
menu.findItem(R.id.share_link_with_position_item).setVisible(isItemAndHasLink);
- boolean isItemHasDownloadLink = media != null && (media instanceof FeedMedia) && ((FeedMedia) media).getDownload_url() != null;
+ boolean isItemHasDownloadLink = isFeedMedia && ((FeedMedia) media).getDownload_url() != null;
menu.findItem(R.id.share_download_url_item).setVisible(isItemHasDownloadLink);
menu.findItem(R.id.share_download_url_with_position_item).setVisible(isItemHasDownloadLink);
+ menu.findItem(R.id.share_file).setVisible(isFeedMedia && ((FeedMedia) media).fileExists());
menu.findItem(R.id.share_item).setVisible(hasWebsiteLink || isItemAndHasLink || isItemHasDownloadLink);
menu.findItem(R.id.add_to_favorites_item).setVisible(false);
menu.findItem(R.id.remove_from_favorites_item).setVisible(false);
- if(media != null && media instanceof FeedMedia) {
+ if (isFeedMedia) {
menu.findItem(R.id.add_to_favorites_item).setVisible(!isFavorite);
menu.findItem(R.id.remove_from_favorites_item).setVisible(isFavorite);
}
@@ -559,6 +574,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem(), true);
}
break;
+ case R.id.share_file:
+ if (media instanceof FeedMedia) {
+ ShareUtils.shareFeedItemFile(this, ((FeedMedia) media));
+ }
+ break;
default:
return false;
}
@@ -627,17 +647,16 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
*/
protected boolean loadMediaInfo() {
Log.d(TAG, "loadMediaInfo()");
+ if(controller == null || controller.getMedia() == null) {
+ return false;
+ }
Playable media = controller.getMedia();
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT, false);
- if (media != null) {
- onPositionObserverUpdate();
- checkFavorite();
- updatePlaybackSpeedButton();
- return true;
- } else {
- return false;
- }
+ onPositionObserverUpdate();
+ checkFavorite();
+ updatePlaybackSpeedButton();
+ return true;
}
protected void updatePlaybackSpeedButton() {
@@ -648,6 +667,91 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
// Only meaningful on AudioplayerActivity, where it is overridden.
}
+ /**
+ * Abstract directions to skip forward or back (rewind) and encapsulates behavior to get or set preference (including update of UI on the skip buttons).
+ */
+ static public enum SkipDirection {
+ SKIP_FORWARD(
+ UserPreferences::getFastForwardSecs,
+ MediaplayerActivity::getTxtvFFFromActivity,
+ UserPreferences::setFastForwardSecs,
+ R.string.pref_fast_forward),
+ SKIP_REWIND(UserPreferences::getRewindSecs,
+ MediaplayerActivity::getTxtvRevFromActivity,
+ UserPreferences::setRewindSecs,
+ R.string.pref_rewind);
+
+ private final Supplier<Integer> getPrefSecsFn;
+ private final Func1<MediaplayerActivity, TextView> getTextViewFn;
+ private final Action1<Integer> setPrefSecsFn;
+ private final int titleResourceID;
+
+ /**
+ * Constructor for skip direction enum. Stores references to utility functions and resource
+ * id's that vary dependending on the direction.
+ *
+ * @param getPrefSecsFn Handle to function that retrieves current seconds of the skip delta
+ * @param getTextViewFn Handle to function that gets the TextView which displays the current skip delta value
+ * @param setPrefSecsFn Handle to function that sets the preference (setting) for the skip delta value (and optionally updates the button label with the current values)
+ * @param titleResourceID ID of the resource string with the title for a view
+ */
+ SkipDirection(Supplier<Integer> getPrefSecsFn, Func1<MediaplayerActivity, TextView> getTextViewFn, Action1<Integer> setPrefSecsFn, int titleResourceID) {
+ this.getPrefSecsFn = getPrefSecsFn;
+ this.getTextViewFn = getTextViewFn;
+ this.setPrefSecsFn = setPrefSecsFn;
+ this.titleResourceID = titleResourceID;
+ }
+
+
+ public int getPrefSkipSeconds() {
+ return(getPrefSecsFn.get());
+ }
+
+ /**
+ * Updates preferences for a forward or backward skip depending on the direction of the instance, optionally updating the UI.
+ *
+ * @param seconds Number of seconds to set the preference associated with the direction of the instance.
+ * @param activity MediaplyerActivity that contains textview to update the display of the skip delta setting (or null if nothing to update)
+ */
+ public void setPrefSkipSeconds(int seconds, @Nullable Activity activity) {
+ setPrefSecsFn.call(seconds);
+
+ if (activity != null && activity instanceof MediaplayerActivity) {
+ TextView tv = getTextViewFn.call((MediaplayerActivity)activity);
+ if (tv != null) tv.setText(String.valueOf(seconds));
+ }
+ }
+ public int getTitleResourceID() {
+ return titleResourceID;
+ }
+ }
+
+ static public void showSkipPreference(Activity activity, SkipDirection direction) {
+ int checked = 0;
+ int skipSecs = direction.getPrefSkipSeconds();
+ final int[] values = activity.getResources().getIntArray(R.array.seek_delta_values);
+ final String[] choices = new String[values.length];
+ for (int i = 0; i < values.length; i++) {
+ if (skipSecs == values[i]) {
+ checked = i;
+ }
+ choices[i] = String.valueOf(values[i]) + " " + activity.getString(R.string.time_seconds);
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setTitle(direction.getTitleResourceID());
+ builder.setSingleChoiceItems(choices, checked, null);
+ builder.setNegativeButton(R.string.cancel_label, null);
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
+ int choice = ((AlertDialog)dialog).getListView().getCheckedItemPosition();
+ if (choice < 0 || choice >= values.length) {
+ System.err.printf("Choice in showSkipPreference is out of bounds %d", choice);
+ } else {
+ direction.setPrefSkipSeconds(values[choice], activity);
+ }
+ });
+ builder.create().show();
+ }
protected void setupGUI() {
setContentView(getContentViewResourceId());
@@ -690,7 +794,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
butFF = (ImageButton) findViewById(R.id.butFF);
txtvFF = (TextView) findViewById(R.id.txtvFF);
if (txtvFF != null) {
- txtvFF.setText(String.valueOf(UserPreferences.getFastFowardSecs()));
+ txtvFF.setText(String.valueOf(UserPreferences.getFastForwardSecs()));
}
butSkip = (ImageButton) findViewById(R.id.butSkip);
@@ -702,39 +806,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
if (butRev != null) {
butRev.setOnClickListener(v -> onRewind());
- butRev.setOnLongClickListener(new View.OnLongClickListener() {
-
- int choice;
-
- @Override
- public boolean onLongClick(View v) {
- int checked = 0;
- int rewindSecs = UserPreferences.getRewindSecs();
- final int[] values = getResources().getIntArray(R.array.seek_delta_values);
- final String[] choices = new String[values.length];
- for (int i = 0; i < values.length; i++) {
- if (rewindSecs == values[i]) {
- checked = i;
- }
- choices[i] = String.valueOf(values[i]) + " " + getString(R.string.time_seconds);
- }
- choice = values[checked];
- AlertDialog.Builder builder = new AlertDialog.Builder(MediaplayerActivity.this);
- builder.setTitle(R.string.pref_rewind);
- builder.setSingleChoiceItems(choices, checked,
- (dialog, which) -> {
- choice = values[which];
- });
- builder.setNegativeButton(R.string.cancel_label, null);
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- UserPreferences.setPrefRewindSecs(choice);
- if(txtvRev != null){
- txtvRev.setText(String.valueOf(choice));
- }
- });
- builder.create().show();
- return true;
- }
+ butRev.setOnLongClickListener(v -> {
+ showSkipPreference(MediaplayerActivity.this, SkipDirection.SKIP_REWIND);
+ return true;
});
}
@@ -742,39 +816,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
if (butFF != null) {
butFF.setOnClickListener(v -> onFastForward());
- butFF.setOnLongClickListener(new View.OnLongClickListener() {
-
- int choice;
-
- @Override
- public boolean onLongClick(View v) {
- int checked = 0;
- int rewindSecs = UserPreferences.getFastFowardSecs();
- final int[] values = getResources().getIntArray(R.array.seek_delta_values);
- final String[] choices = new String[values.length];
- for (int i = 0; i < values.length; i++) {
- if (rewindSecs == values[i]) {
- checked = i;
- }
- choices[i] = String.valueOf(values[i]) + " " + getString(R.string.time_seconds);
- }
- choice = values[checked];
- AlertDialog.Builder builder = new AlertDialog.Builder(MediaplayerActivity.this);
- builder.setTitle(R.string.pref_fast_forward);
- builder.setSingleChoiceItems(choices, checked,
- (dialog, which) -> {
- choice = values[which];
- });
- builder.setNegativeButton(R.string.cancel_label, null);
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- UserPreferences.setPrefFastForwardSecs(choice);
- if(txtvFF != null) {
- txtvFF.setText(String.valueOf(choice));
- }
- });
- builder.create().show();
- return true;
- }
+ butFF.setOnLongClickListener(v -> {
+ showSkipPreference(MediaplayerActivity.this, SkipDirection.SKIP_FORWARD);
+ return false;
});
}
@@ -803,7 +847,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
return;
}
int curr = controller.getPosition();
- controller.seekTo(curr + UserPreferences.getFastFowardSecs() * 1000);
+ controller.seekTo(curr + UserPreferences.getFastForwardSecs() * 1000);
}
protected abstract int getContentViewResourceId();
@@ -865,10 +909,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
isFavorite = isFav;
invalidateOptionsMenu();
}
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- }
- );
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java
index 647745e39..b3cda69d3 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java
@@ -8,6 +8,7 @@ import android.content.res.Configuration;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
+import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
@@ -36,6 +37,7 @@ import de.danoeh.antennapod.adapter.ChaptersListAdapter;
import de.danoeh.antennapod.adapter.NavListAdapter;
import de.danoeh.antennapod.core.asynctask.FeedRemover;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.event.MessageEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedMedia;
@@ -43,9 +45,11 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
+import de.danoeh.antennapod.dialog.RenameFeedDialog;
import de.danoeh.antennapod.fragment.AddFeedFragment;
import de.danoeh.antennapod.fragment.ChaptersFragment;
import de.danoeh.antennapod.fragment.CoverFragment;
@@ -57,6 +61,7 @@ import de.danoeh.antennapod.fragment.QueueFragment;
import de.danoeh.antennapod.fragment.SubscriptionFragment;
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
import de.danoeh.antennapod.preferences.PreferenceController;
+import de.greenrobot.event.EventBus;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
@@ -102,6 +107,12 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
private Subscription subscription;
@Override
+ protected void onPause() {
+ super.onPause();
+ EventBus.getDefault().unregister(this);
+ }
+
+ @Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop()");
@@ -168,8 +179,10 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
pagerAdapter.onMediaChanged(media);
pagerAdapter.setController(controller);
}
+ DBTasks.checkShouldRefreshFeeds(getApplicationContext());
EventDistributor.getInstance().register(contentUpdate);
+ EventBus.getDefault().register(this);
loadData();
}
@@ -277,7 +290,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
if (!super.loadMediaInfo()) {
return false;
}
- if(controller.getMedia() != media) {
+ if(controller != null && controller.getMedia() != media) {
media = controller.getMedia();
pagerAdapter.onMediaChanged(media);
}
@@ -370,6 +383,9 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
case R.id.mark_all_read_item:
DBWriter.markFeedRead(feed.getId());
return true;
+ case R.id.rename_item:
+ new RenameFeedDialog(this, feed).show();
+ return true;
case R.id.remove_item:
final FeedRemover remover = new FeedRemover(this, feed) {
@Override
@@ -379,7 +395,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
};
ConfirmationDialog conDialog = new ConfirmationDialog(this,
R.string.remove_feed_label,
- R.string.feed_delete_confirmation_msg) {
+ getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
@Override
public void onConfirmButtonPressed(
DialogInterface dialog) {
@@ -443,9 +459,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]);
}
});
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- UserPreferences.setHiddenDrawerItems(hiddenDrawerItems);
- });
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> UserPreferences.setHiddenDrawerItems(hiddenDrawerItems));
builder.setNegativeButton(R.string.cancel_label, null);
builder.create().show();
}
@@ -461,12 +475,20 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
if (navAdapter != null) {
navAdapter.notifyDataSetChanged();
}
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
-
+ public void onEventMainThread(MessageEvent event) {
+ Log.d(TAG, "onEvent(" + event + ")");
+ View parentLayout = findViewById(R.id.drawer_layout);
+ Snackbar snackbar = Snackbar.make(parentLayout, event.message, Snackbar.LENGTH_SHORT);
+ if (event.action != null) {
+ snackbar.setAction(getString(R.string.undo), v -> {
+ event.action.run();
+ });
+ }
+ snackbar.show();
+ }
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
index a53f9bdb8..f6bf11e66 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
@@ -29,7 +29,6 @@ import com.bumptech.glide.Glide;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
-import org.jsoup.examples.HtmlToPlainText;
import org.jsoup.nodes.Document;
import java.io.File;
@@ -63,6 +62,7 @@ import de.danoeh.antennapod.core.util.FileNameGenerator;
import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.core.util.URLChecker;
import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer;
+import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
import de.danoeh.antennapod.dialog.AuthenticationDialog;
import de.greenrobot.event.EventBus;
import rx.Observable;
@@ -81,17 +81,12 @@ import rx.schedulers.Schedulers;
*/
public class OnlineFeedViewActivity extends AppCompatActivity {
- private static final String TAG = "OnlineFeedViewActivity";
-
public static final String ARG_FEEDURL = "arg.feedurl";
-
// Optional argument: specify a title for the actionbar.
public static final String ARG_TITLE = "title";
-
- private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE;
-
public static final int RESULT_ERROR = 2;
-
+ private static final String TAG = "OnlineFeedViewActivity";
+ private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE;
private volatile List<Feed> feeds;
private Feed feed;
private String selectedDownloadUrl;
@@ -106,22 +101,19 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
private Subscription download;
private Subscription parser;
private Subscription updater;
-
- public void onEventMainThread(DownloadEvent event) {
- Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
- setSubscribeButtonState(feed);
- }
-
private EventDistributor.EventListener listener = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
if ((arg & EventDistributor.FEED_LIST_UPDATE) != 0) {
- updater = Observable.fromCallable(() -> DBReader.getFeedList())
+ updater = Observable.fromCallable(DBReader::getFeedList)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(feeds -> {
+ .subscribe(
+ feeds -> {
OnlineFeedViewActivity.this.feeds = feeds;
setSubscribeButtonState(feed);
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
}
);
} else if ((arg & EVENTS) != 0) {
@@ -130,6 +122,11 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
}
};
+ public void onEventMainThread(DownloadEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ setSubscribeButtonState(feed);
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
@@ -149,7 +146,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|| TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) {
feedUrl = (TextUtils.equals(getIntent().getAction(), Intent.ACTION_SEND))
? getIntent().getStringExtra(Intent.EXTRA_TEXT) : getIntent().getDataString();
- getSupportActionBar().setTitle(R.string.add_new_feed_label);
+ getSupportActionBar().setTitle(R.string.add_feed_label);
} else {
throw new IllegalArgumentException("Activity must be started with feedurl argument!");
}
@@ -281,30 +278,33 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(status -> {
- if (status != null) {
- if (!status.isCancelled()) {
- if (status.isSuccessful()) {
- parseFeed();
- } else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) {
- if (!isFinishing() && !isPaused) {
- dialog = new FeedViewAuthenticationDialog(OnlineFeedViewActivity.this,
- R.string.authentication_notification_title, downloader.getDownloadRequest().getSource());
- dialog.show();
- }
- } else {
- String errorMsg = status.getReason().getErrorString(OnlineFeedViewActivity.this);
- if (errorMsg != null && status.getReasonDetailed() != null) {
- errorMsg += " (" + status.getReasonDetailed() + ")";
- }
- showErrorDialog(errorMsg);
- }
- }
- } else {
- Log.wtf(TAG, "DownloadStatus returned by Downloader was null");
- finish();
- }
- });
+ .subscribe(this::checkDownloadResult,
+ error -> Log.e(TAG, Log.getStackTraceString(error)));
+ }
+
+ private void checkDownloadResult(DownloadStatus status) {
+ if (status == null) {
+ Log.wtf(TAG, "DownloadStatus returned by Downloader was null");
+ finish();
+ }
+ if (status.isCancelled()) {
+ return;
+ }
+ if (status.isSuccessful()) {
+ parseFeed();
+ } else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) {
+ if (!isFinishing() && !isPaused) {
+ dialog = new FeedViewAuthenticationDialog(OnlineFeedViewActivity.this,
+ R.string.authentication_notification_title, downloader.getDownloadRequest().getSource());
+ dialog.show();
+ }
+ } else {
+ String errorMsg = status.getReason().getErrorString(OnlineFeedViewActivity.this);
+ if (errorMsg != null && status.getReasonDetailed() != null) {
+ errorMsg += " (" + status.getReasonDetailed() + ")";
+ }
+ showErrorDialog(errorMsg);
+ }
}
private void parseFeed() {
@@ -354,14 +354,19 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
* This method is executed on a background thread
*/
private void beforeShowFeedInformation(Feed feed) {
- // remove HTML tags from descriptions
+ final HtmlToPlainText formatter = new HtmlToPlainText();
+ if(Feed.TYPE_ATOM1.equals(feed.getType()) && feed.getDescription() != null) {
+ // remove HTML tags from descriptions
+ Log.d(TAG, "Removing HTML from feed description");
+ Document feedDescription = Jsoup.parse(feed.getDescription());
+ feed.setDescription(StringUtils.trim(formatter.getPlainText(feedDescription)));
+ }
Log.d(TAG, "Removing HTML from shownotes");
if (feed.getItems() != null) {
- HtmlToPlainText formatter = new HtmlToPlainText();
for (FeedItem item : feed.getItems()) {
if (item.getDescription() != null) {
- Document description = Jsoup.parse(item.getDescription());
- item.setDescription(StringUtils.trim(formatter.getPlainText(description)));
+ Document itemDescription = Jsoup.parse(item.getDescription());
+ item.setDescription(StringUtils.trim(formatter.getPlainText(itemDescription)));
}
}
}
@@ -514,9 +519,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
builder.setMessage(R.string.error_msg_prefix);
}
builder.setNeutralButton(android.R.string.ok,
- (dialog, which) -> {
- dialog.cancel();
- }
+ (dialog, which) -> dialog.cancel()
);
builder.setOnCancelListener(dialog -> {
setResult(RESULT_ERROR);
@@ -585,7 +588,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
private String feedUrl;
- public FeedViewAuthenticationDialog(Context context, int titleRes, String feedUrl) {
+ FeedViewAuthenticationDialog(Context context, int titleRes, String feedUrl) {
super(context, titleRes, true, false, null, null);
this.feedUrl = feedUrl;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java
index fce50bd1c..cd375a65a 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java
@@ -15,7 +15,7 @@ import java.util.ArrayList;
import java.util.List;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.opml.OpmlElement;
+import de.danoeh.antennapod.core.export.opml.OpmlElement;
import de.danoeh.antennapod.core.preferences.UserPreferences;
/**
@@ -23,10 +23,8 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
* which feeds he wants to import.
*/
public class OpmlFeedChooserActivity extends AppCompatActivity {
- private static final String TAG = "OpmlFeedChooserActivity";
-
public static final String EXTRA_SELECTED_ITEMS = "de.danoeh.antennapod.selectedItems";
-
+ private static final String TAG = "OpmlFeedChooserActivity";
private Button butConfirm;
private Button butCancel;
private ListView feedlist;
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
index 8726af281..07b0b3cdb 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
@@ -3,6 +3,7 @@ package de.danoeh.antennapod.activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
+import android.os.Build;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
@@ -20,7 +21,7 @@ import java.util.ArrayList;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.asynctask.OpmlFeedQueuer;
import de.danoeh.antennapod.asynctask.OpmlImportWorker;
-import de.danoeh.antennapod.core.opml.OpmlElement;
+import de.danoeh.antennapod.core.export.opml.OpmlElement;
import de.danoeh.antennapod.core.util.LangUtils;
/**
@@ -29,9 +30,8 @@ import de.danoeh.antennapod.core.util.LangUtils;
public class OpmlImportBaseActivity extends AppCompatActivity {
private static final String TAG = "OpmlImportBaseActivity";
- private OpmlImportWorker importWorker;
-
private static final int PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 5;
+ private OpmlImportWorker importWorker;
@Nullable private Uri uri;
/**
@@ -77,7 +77,8 @@ public class OpmlImportBaseActivity extends AppCompatActivity {
return;
}
this.uri = uri;
- if(uri.toString().contains(Environment.getExternalStorageDirectory().toString())) {
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
+ uri.toString().contains(Environment.getExternalStorageDirectory().toString())) {
int permission = ActivityCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
requestPermission();
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java
index 02e16a7b5..4c94e2b76 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java
@@ -1,25 +1,30 @@
package de.danoeh.antennapod.activity;
+import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import de.danoeh.antennapod.core.preferences.UserPreferences;
-/** Lets the user start the OPML-import process. */
+/**
+ * Lets the user start the OPML-import process.
+ */
public class OpmlImportFromIntentActivity extends OpmlImportBaseActivity {
private static final String TAG = "OpmlImportFromIntentAct";
@Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
+ protected void onCreate(Bundle savedInstanceState) {
+ setTheme(UserPreferences.getTheme());
+ super.onCreate(savedInstanceState);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Uri uri = getIntent().getData();
- if(uri.toString().startsWith("/")) {
+ if (uri != null && uri.toString().startsWith("/")) {
uri = Uri.parse("file://" + uri.toString());
+ } else {
+ uri = Uri.parse(getIntent().getStringExtra(Intent.EXTRA_TEXT));
}
importUri(uri);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java
index b2dab7f68..eb6b473d2 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java
@@ -135,7 +135,7 @@ public class OpmlImportFromPathActivity extends OpmlImportBaseActivity {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == CHOOSE_OPML_FILE) {
Uri uri = data.getData();
- if(uri.toString().startsWith("/")) {
+ if(uri != null && uri.toString().startsWith("/")) {
uri = Uri.parse("file://" + uri.toString());
}
importUri(uri);
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java
index 3a1a7be05..dc5570dc0 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java
@@ -1,9 +1,9 @@
package de.danoeh.antennapod.activity;
-import de.danoeh.antennapod.core.opml.OpmlElement;
-
import java.util.ArrayList;
+import de.danoeh.antennapod.core.export.opml.OpmlElement;
+
/**
* Hold infos gathered by Ompl-Import
* <p/>
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java
index ba22a42b4..dd932814f 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java
@@ -26,11 +26,9 @@ import de.danoeh.antennapod.preferences.PreferenceController;
*/
public class PreferenceActivity extends AppCompatActivity {
+ private static WeakReference<PreferenceActivity> instance;
private PreferenceController preferenceController;
private MainFragment prefFragment;
- private static WeakReference<PreferenceActivity> instance;
-
-
private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
@@ -103,6 +101,7 @@ public class PreferenceActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setRetainInstance(true);
addPreferencesFromResource(R.xml.preferences);
PreferenceActivity activity = instance.get();
if(activity != null && activity.preferenceController != null) {
@@ -118,5 +117,23 @@ public class PreferenceActivity extends AppCompatActivity {
activity.preferenceController.onResume();
}
}
+
+ @Override
+ public void onPause() {
+ PreferenceActivity activity = instance.get();
+ if(activity != null && activity.preferenceController != null) {
+ activity.preferenceController.onPause();
+ }
+ super.onPause();
+ }
+
+ @Override
+ public void onStop() {
+ PreferenceActivity activity = instance.get();
+ if(activity != null && activity.preferenceController != null) {
+ activity.preferenceController.onStop();
+ }
+ super.onStop();
+ }
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java
index 633f8d66d..390bec15c 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java
@@ -18,9 +18,6 @@ import de.danoeh.antennapod.preferences.PreferenceController;
*/
public class PreferenceActivityGingerbread extends android.preference.PreferenceActivity {
private static final String TAG = "PreferenceActivity";
-
- private PreferenceController preferenceController;
-
private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() {
@SuppressWarnings("deprecation")
@@ -34,6 +31,7 @@ public class PreferenceActivityGingerbread extends android.preference.Preference
return PreferenceActivityGingerbread.this;
}
};
+ private PreferenceController preferenceController;
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
@@ -55,6 +53,18 @@ public class PreferenceActivityGingerbread extends android.preference.Preference
}
@Override
+ protected void onPause() {
+ preferenceController.onPause();
+ super.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ preferenceController.onStop();
+ super.onStop();
+ }
+
+ @Override
protected void onApplyThemeResource(Theme theme, int resid, boolean first) {
theme.applyStyle(UserPreferences.getTheme(), true);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java
new file mode 100644
index 000000000..b92ac8577
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java
@@ -0,0 +1,23 @@
+package de.danoeh.antennapod.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+
+/**
+ * Creator: vbarad
+ * Date: 2016-12-03
+ * Project: AntennaPod
+ */
+
+public class SplashActivity extends AppCompatActivity {
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent intent = new Intent(this, MainActivity.class);
+ startActivity(intent);
+ finish();
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java
index 0254617e4..b2ff43c43 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java
@@ -1,14 +1,18 @@
package de.danoeh.antennapod.activity;
+import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.ProgressBar;
+import android.widget.RadioButton;
import android.widget.TextView;
import de.danoeh.antennapod.R;
@@ -28,12 +32,16 @@ public class StatisticsActivity extends AppCompatActivity
implements AdapterView.OnItemClickListener {
private static final String TAG = StatisticsActivity.class.getSimpleName();
+ private static final String PREF_NAME = "StatisticsActivityPrefs";
+ private static final String PREF_COUNT_ALL = "countAll";
private Subscription subscription;
private TextView totalTimeTextView;
private ListView feedStatisticsList;
private ProgressBar progressBar;
private StatisticsListAdapter listAdapter;
+ private boolean countAll = false;
+ private SharedPreferences prefs;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -42,10 +50,14 @@ public class StatisticsActivity extends AppCompatActivity
getSupportActionBar().setDisplayShowHomeEnabled(true);
setContentView(R.layout.statistics_activity);
+ prefs = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
+ countAll = prefs.getBoolean(PREF_COUNT_ALL, false);
+
totalTimeTextView = (TextView) findViewById(R.id.total_time);
feedStatisticsList = (ListView) findViewById(R.id.statistics_list);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
listAdapter = new StatisticsListAdapter(this);
+ listAdapter.setCountAll(countAll);
feedStatisticsList.setAdapter(listAdapter);
feedStatisticsList.setOnItemClickListener(this);
}
@@ -53,10 +65,15 @@ public class StatisticsActivity extends AppCompatActivity
@Override
public void onResume() {
super.onResume();
- progressBar.setVisibility(View.VISIBLE);
- totalTimeTextView.setVisibility(View.GONE);
- feedStatisticsList.setVisibility(View.GONE);
- loadStats();
+ refreshStatistics();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.statistics, menu);
+ return true;
}
@Override
@@ -64,30 +81,60 @@ public class StatisticsActivity extends AppCompatActivity
if (item.getItemId() == android.R.id.home) {
finish();
return true;
+ } else if (item.getItemId() == R.id.statistics_mode) {
+ selectStatisticsMode();
+ return true;
} else {
return super.onOptionsItemSelected(item);
}
}
- private void loadStats() {
- if(subscription != null) {
+ private void selectStatisticsMode() {
+ View contentView = View.inflate(this, R.layout.statistics_mode_select_dialog, null);
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setView(contentView);
+ builder.setTitle(R.string.statistics_mode);
+
+ if (countAll) {
+ ((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).setChecked(true);
+ } else {
+ ((RadioButton) contentView.findViewById(R.id.statistics_mode_normal)).setChecked(true);
+ }
+
+ builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
+ countAll = ((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).isChecked();
+ listAdapter.setCountAll(countAll);
+ prefs.edit().putBoolean(PREF_COUNT_ALL, countAll).apply();
+ refreshStatistics();
+ });
+
+ builder.show();
+ }
+
+ private void refreshStatistics() {
+ progressBar.setVisibility(View.VISIBLE);
+ totalTimeTextView.setVisibility(View.GONE);
+ feedStatisticsList.setVisibility(View.GONE);
+ loadStatistics();
+ }
+
+ private void loadStatistics() {
+ if (subscription != null) {
subscription.unsubscribe();
}
- subscription = Observable.fromCallable(() -> DBReader.getStatistics())
+ subscription = Observable.fromCallable(() -> DBReader.getStatistics(countAll))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
if (result != null) {
totalTimeTextView.setText(Converter
- .shortLocalizedDuration(this, result.totalTime));
+ .shortLocalizedDuration(this, countAll ? result.totalTimeCountAll : result.totalTime));
listAdapter.update(result.feedTime);
progressBar.setVisibility(View.GONE);
totalTimeTextView.setVisibility(View.VISIBLE);
feedStatisticsList.setVisibility(View.VISIBLE);
}
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
@Override
@@ -97,9 +144,10 @@ public class StatisticsActivity extends AppCompatActivity
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle(stats.feed.getTitle());
dialog.setMessage(getString(R.string.statistics_details_dialog,
- stats.episodesStarted,
+ countAll ? stats.episodesStartedIncludingMarked : stats.episodesStarted,
stats.episodes,
- Converter.shortLocalizedDuration(this, stats.timePlayed),
+ Converter.shortLocalizedDuration(this, countAll ?
+ stats.timePlayedCountAll : stats.timePlayed),
Converter.shortLocalizedDuration(this, stats.time)));
dialog.setPositiveButton(android.R.string.ok, null);
dialog.show();
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java
index 81d727283..62bff0891 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java
@@ -55,7 +55,7 @@ public class StorageErrorActivity extends AppCompatActivity {
openDirectoryChooser();
}
});
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int readPermission = ActivityCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE);
int writePermission = ActivityCompat.checkSelfPermission(this,
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java
index d46a3d6c2..8ede947c5 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java
@@ -6,11 +6,13 @@ import android.content.res.Configuration;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
@@ -40,7 +42,7 @@ import de.danoeh.antennapod.core.service.GpodnetSyncService;
* Step 2: Choose device from a list of available devices or create a new one
* Step 3: Choose from a list of actions
*/
-public class GpodnetAuthenticationActivity extends ActionBarActivity {
+public class GpodnetAuthenticationActivity extends AppCompatActivity {
private static final String TAG = "GpodnetAuthActivity";
private static final String CURRENT_STEP = "current_step";
@@ -113,6 +115,9 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
final TextView txtvError = (TextView) view.findViewById(R.id.txtvError);
final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.progBarLogin);
+ password.setOnEditorActionListener((v, actionID, event) ->
+ actionID == EditorInfo.IME_ACTION_GO && login.performClick());
+
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -131,6 +136,11 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
login.setEnabled(false);
progressBar.setVisibility(View.VISIBLE);
txtvError.setVisibility(View.GONE);
+ // hide the keyboard
+ InputMethodManager inputManager = (InputMethodManager)
+ getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputManager.hideSoftInputFromWindow(login.getWindowToken(),
+ InputMethodManager.HIDE_NOT_ALWAYS);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java
index 66e6f9a00..c18564351 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java
@@ -1,8 +1,9 @@
package de.danoeh.antennapod.adapter;
import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.util.LongList;
public interface ActionButtonCallback {
/** Is called when the action button of a list item has been pressed. */
- void onActionButtonPressed(FeedItem item);
+ void onActionButtonPressed(FeedItem item, LongList queueIds);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java
index 1a8f0a67a..f0210f983 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java
@@ -47,6 +47,7 @@ public class ActionButtonUtils {
* Sets the displayed bitmap and content description of the given
* action button so that it matches the state of the FeedItem.
*/
+ @SuppressWarnings("ResourceType")
public void configureActionButton(ImageButton butSecondary, FeedItem item, boolean isInQueue) {
Validate.isTrue(butSecondary != null && item != null, "butSecondary or item was null");
@@ -57,8 +58,7 @@ public class ActionButtonUtils {
if (isDownloadingMedia) {
// item is being downloaded
butSecondary.setVisibility(View.VISIBLE);
- butSecondary.setImageDrawable(drawables
- .getDrawable(1));
+ butSecondary.setImageDrawable(drawables.getDrawable(1));
butSecondary.setContentDescription(context.getString(labels[1]));
} else {
// item is not downloaded and not being downloaded
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java
index 8aaf0055a..5c58d00f2 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java
@@ -15,7 +15,7 @@ import de.danoeh.antennapod.core.util.NetworkUtils;
/**
* Utility methods for adapters
*/
-public class AdapterUtils {
+class AdapterUtils {
private static final String TAG = AdapterUtils.class.getSimpleName();
@@ -26,7 +26,7 @@ public class AdapterUtils {
/**
* Updates the contents of the TextView that shows the current playback position and the ProgressBar.
*/
- public static void updateEpisodePlaybackProgress(FeedItem item, TextView txtvPos, ProgressBar episodeProgress) {
+ static void updateEpisodePlaybackProgress(FeedItem item, TextView txtvPos, ProgressBar episodeProgress) {
FeedMedia media = item.getMedia();
episodeProgress.setVisibility(View.GONE);
if (media == null) {
@@ -47,7 +47,6 @@ public class AdapterUtils {
- media.getPosition()));
}
} else if (!media.isDownloaded()) {
- Log.d(TAG, "size: " + media.getSize());
if (media.getSize() > 0) {
txtvPos.setText(Converter.byteToString(media.getSize()));
} else if(NetworkUtils.isDownloadAllowed() && !media.checkedOnSizeButUnknown()) {
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
index 43a00f7c5..3e8bbc488 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
@@ -200,11 +200,11 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.butSecondary.setOnClickListener(secondaryActionListener);
Glide.with(mainActivityRef.get())
- .load(item.getImageUri())
+ .load(item.getImageLocation())
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
.dontAnimate()
- .into(new CoverTarget(item.getFeed().getImageUri(), holder.placeholder, holder.cover, mainActivityRef.get()));
+ .into(new CoverTarget(item.getFeed().getImageLocation(), holder.placeholder, holder.cover, mainActivityRef.get()));
}
@Override
@@ -232,7 +232,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
@Override
public void onClick(View v) {
FeedItem item = (FeedItem) v.getTag();
- actionButtonCallback.onActionButtonPressed(item);
+ actionButtonCallback.onActionButtonPressed(item, itemAccess.getQueueIds());
}
};
@@ -319,6 +319,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
boolean isInQueue(FeedItem item);
+ LongList getQueueIds();
+
}
/**
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
index 37e00ab74..d7bebb672 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
@@ -60,6 +60,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
defaultTextColor = holder.title.getTextColors().getDefaultColor();
holder.start = (TextView) convertView.findViewById(R.id.txtvStart);
holder.link = (TextView) convertView.findViewById(R.id.txtvLink);
+ holder.duration = (TextView) convertView.findViewById(R.id.txtvDuration);
holder.butPlayChapter = (ImageButton) convertView.findViewById(R.id.butPlayChapter);
convertView.setTag(holder);
} else {
@@ -70,6 +71,16 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
holder.title.setText(sc.getTitle());
holder.start.setText(Converter.getDurationStringLong((int) sc
.getStart()));
+
+ long duration;
+ if (position + 1 < media.getChapters().size()) {
+ duration = media.getChapters().get(position + 1).getStart() - sc.getStart();
+ } else {
+ duration = media.getDuration() - sc.getStart();
+ }
+ holder.duration.setText(getContext().getString(R.string.chapter_duration,
+ Converter.getDurationStringLong((int) duration)));
+
if (sc.getLink() != null) {
holder.link.setVisibility(View.VISIBLE);
holder.link.setText(sc.getLink());
@@ -155,6 +166,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
TextView title;
TextView start;
TextView link;
+ TextView duration;
ImageButton butPlayChapter;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java b/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java
index ed0c08086..538af8c79 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java
@@ -18,12 +18,12 @@ import de.danoeh.antennapod.core.glide.ApGlideSettings;
class CoverTarget extends GlideDrawableImageViewTarget {
- private final WeakReference<Uri> fallback;
+ private final WeakReference<String> fallback;
private final WeakReference<TextView> placeholder;
private final WeakReference<ImageView> cover;
private final WeakReference<MainActivity> mainActivity;
- public CoverTarget(Uri fallbackUri, TextView txtvPlaceholder, ImageView imgvCover, MainActivity activity) {
+ public CoverTarget(String fallbackUri, TextView txtvPlaceholder, ImageView imgvCover, MainActivity activity) {
super(imgvCover);
fallback = new WeakReference<>(fallbackUri);
placeholder = new WeakReference<>(txtvPlaceholder);
@@ -33,7 +33,7 @@ class CoverTarget extends GlideDrawableImageViewTarget {
@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
- Uri fallbackUri = fallback.get();
+ String fallbackUri = fallback.get();
TextView txtvPlaceholder = placeholder.get();
ImageView imgvCover = cover.get();
if (fallbackUri != null && txtvPlaceholder != null && imgvCover != null) {
@@ -48,7 +48,7 @@ class CoverTarget extends GlideDrawableImageViewTarget {
}
@Override
- public void onResourceReady(GlideDrawable drawable, GlideAnimation anim) {
+ public void onResourceReady(GlideDrawable drawable, GlideAnimation<? super GlideDrawable> anim) {
super.onResourceReady(drawable, anim);
TextView txtvPlaceholder = placeholder.get();
if (txtvPlaceholder != null) {
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
index 00ab96f6c..4a53be9dc 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
@@ -51,13 +51,12 @@ public class DefaultActionButtonCallback implements ActionButtonCallback {
}
@Override
- public void onActionButtonPressed(final FeedItem item) {
+ public void onActionButtonPressed(final FeedItem item, final LongList queueIds) {
if (item.hasMedia()) {
final FeedMedia media = item.getMedia();
boolean isDownloading = DownloadRequester.getInstance().isDownloadingFile(media);
if (!isDownloading && !media.isDownloaded()) {
- LongList queueIds = DBReader.getQueueIDList();
if (NetworkUtils.isDownloadAllowed() || userAllowedMobileDownloads()) {
try {
DBTasks.downloadFeedItems(context, item);
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
index 6d0beff9e..6907e467b 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
@@ -12,6 +12,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
+import com.nineoldandroids.view.ViewHelper;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -77,7 +78,7 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
}
Glide.with(context)
- .load(item.getImageUri())
+ .load(item.getImageLocation())
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
@@ -85,6 +86,12 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
.dontAnimate()
.into(holder.imageView);
+ if(item.isPlayed()) {
+ ViewHelper.setAlpha(convertView, 0.5f);
+ } else {
+ ViewHelper.setAlpha(convertView, 1.0f);
+ }
+
holder.title.setText(item.getTitle());
holder.txtvSize.setText(Converter.byteToString(item.getMedia().getSize()));
holder.queueStatus.setVisibility(item.isTagged(FeedItem.TAG_QUEUE) ? View.VISIBLE : View.GONE);
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
index 4e9c5d71b..35c42725c 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
@@ -26,6 +26,7 @@ import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.DateUtils;
+import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.ThemeUtils;
/**
@@ -86,6 +87,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
}
@Override
+ @SuppressWarnings("ResourceType")
public View getView(final int position, View convertView, ViewGroup parent) {
Holder holder;
final FeedItem item = getItem(position);
@@ -219,7 +221,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
@Override
public void onClick(View v) {
FeedItem item = (FeedItem) v.getTag();
- callback.onActionButtonPressed(item);
+ callback.onActionButtonPressed(item, itemAccess.getQueueIds());
}
};
@@ -243,6 +245,8 @@ public class FeedItemlistAdapter extends BaseAdapter {
FeedItem getItem(int position);
+ LongList getQueueIds();
+
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
index 75c858ec6..465497b55 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.adapter;
+import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
@@ -21,6 +22,7 @@ import com.joanzapata.iconify.widget.IconTextView;
import org.apache.commons.lang3.ArrayUtils;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -45,6 +47,7 @@ import de.danoeh.antennapod.fragment.SubscriptionFragment;
*/
public class NavListAdapter extends BaseAdapter
implements SharedPreferences.OnSharedPreferenceChangeListener {
+
public static final int VIEW_TYPE_COUNT = 3;
public static final int VIEW_TYPE_NAV = 0;
public static final int VIEW_TYPE_SECTION_DIVIDER = 1;
@@ -60,12 +63,12 @@ public class NavListAdapter extends BaseAdapter
private static String[] titles;
private ItemAccess itemAccess;
- private Context context;
+ private WeakReference<Activity> activity;
private boolean showSubscriptionList = true;
- public NavListAdapter(ItemAccess itemAccess, Context context) {
+ public NavListAdapter(ItemAccess itemAccess, Activity context) {
this.itemAccess = itemAccess;
- this.context = context;
+ this.activity = new WeakReference<>(context);
titles = context.getResources().getStringArray(R.array.nav_drawer_titles);
loadItems();
@@ -108,6 +111,10 @@ public class NavListAdapter extends BaseAdapter
}
private Drawable getDrawable(String tag) {
+ Activity context = activity.get();
+ if(context == null) {
+ return null;
+ }
int icon;
switch (tag) {
case QueueFragment.TAG:
@@ -218,6 +225,10 @@ public class NavListAdapter extends BaseAdapter
}
private View getNavView(String title, int position, View convertView, ViewGroup parent) {
+ Activity context = activity.get();
+ if(context == null) {
+ return null;
+ }
NavHolder holder;
if (convertView == null) {
holder = new NavHolder();
@@ -236,30 +247,28 @@ public class NavListAdapter extends BaseAdapter
holder.title.setText(title);
+ // reset for re-use
+ holder.count.setVisibility(View.GONE);
+ holder.count.setOnClickListener(null);
+
String tag = tags.get(position);
if (tag.equals(QueueFragment.TAG)) {
int queueSize = itemAccess.getQueueSize();
if (queueSize > 0) {
- holder.count.setVisibility(View.VISIBLE);
holder.count.setText(String.valueOf(queueSize));
- } else {
- holder.count.setVisibility(View.GONE);
+ holder.count.setVisibility(View.VISIBLE);
}
} else if (tag.equals(EpisodesFragment.TAG)) {
int unreadItems = itemAccess.getNumberOfNewItems();
if (unreadItems > 0) {
- holder.count.setVisibility(View.VISIBLE);
holder.count.setText(String.valueOf(unreadItems));
- } else {
- holder.count.setVisibility(View.GONE);
+ holder.count.setVisibility(View.VISIBLE);
}
} else if (tag.equals(SubscriptionFragment.TAG)) {
int sum = itemAccess.getFeedCounterSum();
if (sum > 0) {
- holder.count.setVisibility(View.VISIBLE);
holder.count.setText(String.valueOf(sum));
- } else {
- holder.count.setVisibility(View.GONE);
+ holder.count.setVisibility(View.VISIBLE);
}
} else if(tag.equals(DownloadsFragment.TAG) && UserPreferences.isEnableAutodownload()) {
int epCacheSize = UserPreferences.getEpisodeCacheSize();
@@ -278,11 +287,7 @@ public class NavListAdapter extends BaseAdapter
.setPositiveButton(android.R.string.ok, (dialog, which) -> {})
.show()
);
- } else {
- holder.count.setVisibility(View.GONE);
}
- } else {
- holder.count.setVisibility(View.GONE);
}
holder.image.setImageDrawable(getDrawable(tags.get(position)));
@@ -291,6 +296,10 @@ public class NavListAdapter extends BaseAdapter
}
private View getSectionDividerView(View convertView, ViewGroup parent) {
+ Activity context = activity.get();
+ if(context == null) {
+ return null;
+ }
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -303,6 +312,10 @@ public class NavListAdapter extends BaseAdapter
}
private View getFeedView(int position, View convertView, ViewGroup parent) {
+ Activity context = activity.get();
+ if(context == null) {
+ return null;
+ }
int feedPos = position - getSubscriptionOffset();
Feed feed = itemAccess.getItem(feedPos);
@@ -324,7 +337,7 @@ public class NavListAdapter extends BaseAdapter
}
Glide.with(context)
- .load(feed.getImageUri())
+ .load(feed.getImageLocation())
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
index 796ac4184..c6ddc6c86 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
@@ -296,11 +296,11 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
butSecondary.setOnClickListener(secondaryActionListener);
Glide.with(mainActivity.get())
- .load(item.getImageUri())
+ .load(item.getImageLocation())
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
.dontAnimate()
- .into(new CoverTarget(item.getFeed().getImageUri(), placeholder, cover, mainActivity.get()));
+ .into(new CoverTarget(item.getFeed().getImageLocation(), placeholder, cover, mainActivity.get()));
}
}
@@ -309,7 +309,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
@Override
public void onClick(View v) {
FeedItem item = (FeedItem) v.getTag();
- actionButtonCallback.onActionButtonPressed(item);
+ actionButtonCallback.onActionButtonPressed(item, itemAccess.getQueueIds());
}
};
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java
index a68ef01d9..8e1aa24e0 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java
@@ -11,6 +11,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
+import com.nineoldandroids.view.ViewHelper;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.Feed;
@@ -80,7 +81,7 @@ public class SearchlistAdapter extends BaseAdapter {
holder.subtitle.setVisibility(View.GONE);
Glide.with(context)
- .load(feed.getImageUri())
+ .load(feed.getImageLocation())
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
@@ -96,8 +97,10 @@ public class SearchlistAdapter extends BaseAdapter {
holder.subtitle.setText(result.getSubtitle());
}
+ ViewHelper.setAlpha(convertView, item.isPlayed() ? 0.5f : 1.0f);
+
Glide.with(context)
- .load(item.getFeed().getImageUri())
+ .load(item.getFeed().getImageLocation())
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java
index 7fb1472ad..c060083a6 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java
@@ -9,11 +9,9 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
-import com.joanzapata.iconify.widget.IconTextView;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.Feed;
@@ -27,11 +25,15 @@ import de.danoeh.antennapod.core.util.Converter;
public class StatisticsListAdapter extends BaseAdapter {
private Context context;
List<DBReader.StatisticsItem> feedTime = new ArrayList<>();
+ private boolean countAll = true;
public StatisticsListAdapter(Context context) {
this.context = context;
}
+ public void setCountAll(boolean countAll) {
+ this.countAll = countAll;
+ }
@Override
public int getCount() {
@@ -69,7 +71,7 @@ public class StatisticsListAdapter extends BaseAdapter {
}
Glide.with(context)
- .load(feed.getImageUri())
+ .load(feed.getImageLocation())
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
@@ -79,7 +81,8 @@ public class StatisticsListAdapter extends BaseAdapter {
holder.title.setText(feed.getTitle());
holder.time.setText(Converter.shortLocalizedDuration(context,
- feedTime.get(position).timePlayed));
+ countAll ? feedTime.get(position).timePlayedCountAll
+ : feedTime.get(position).timePlayed));
return convertView;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java
index e2561804e..6d19bfa6c 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java
@@ -1,9 +1,7 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
-import android.net.Uri;
import android.support.v4.app.Fragment;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -32,8 +30,8 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
/** placeholder object that indicates item should be added */
public static final Object ADD_ITEM_OBJ = new Object();
- /** the position in the view that holds the add item */
- private static final int ADD_POSITION = 0;
+ /** the position in the view that holds the add item; 0 is the first, -1 is the last position */
+ private static final int ADD_POSITION = -1;
private static final String TAG = "SubscriptionsAdapter";
private final WeakReference<MainActivity> mainActivityRef;
@@ -44,8 +42,16 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
this.itemAccess = itemAccess;
}
+ private int getAddTilePosition() {
+ if(ADD_POSITION < 0) {
+ return ADD_POSITION + getCount();
+ }
+ return ADD_POSITION;
+ }
+
private int getAdjustedPosition(int origPosition) {
- return origPosition - 1;
+ assert(origPosition != getAddTilePosition());
+ return origPosition < getAddTilePosition() ? origPosition : origPosition - 1;
}
@Override
@@ -55,15 +61,20 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
@Override
public Object getItem(int position) {
- if (position == ADD_POSITION) {
+ if (position == getAddTilePosition()) {
return ADD_ITEM_OBJ;
}
return itemAccess.getItem(getAdjustedPosition(position));
}
@Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @Override
public long getItemId(int position) {
- if (position == ADD_POSITION) {
+ if (position == getAddTilePosition()) {
return 0;
}
return itemAccess.getItem(getAdjustedPosition(position)).getId();
@@ -89,13 +100,17 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
holder = (Holder) convertView.getTag();
}
- if (position == ADD_POSITION) {
+ if (position == getAddTilePosition()) {
holder.feedTitle.setText("{md-add 500%}\n\n" + mainActivityRef.get().getString(R.string.add_feed_label));
holder.feedTitle.setVisibility(View.VISIBLE);
// prevent any accidental re-use of old values (not sure how that would happen...)
holder.count.setPrimaryText("");
// make it go away, we don't need it for add feed
holder.count.setVisibility(View.INVISIBLE);
+
+ // when this holder is reused, we could else end up with a cover image
+ Glide.clear(holder.imageView);
+
return convertView;
}
@@ -104,10 +119,15 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
holder.feedTitle.setText(feed.getTitle());
holder.feedTitle.setVisibility(View.VISIBLE);
- holder.count.setPrimaryText(String.valueOf(itemAccess.getFeedCounter(feed.getId())));
- holder.count.setVisibility(View.VISIBLE);
+ int count = itemAccess.getFeedCounter(feed.getId());
+ if(count > 0) {
+ holder.count.setPrimaryText(String.valueOf(itemAccess.getFeedCounter(feed.getId())));
+ holder.count.setVisibility(View.VISIBLE);
+ } else {
+ holder.count.setVisibility(View.GONE);
+ }
Glide.with(mainActivityRef.get())
- .load(feed.getImageUri())
+ .load(feed.getImageLocation())
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
@@ -119,7 +139,7 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- if (position == ADD_POSITION) {
+ if (position == getAddTilePosition()) {
mainActivityRef.get().loadChildFragment(new AddFeedFragment());
} else {
Fragment fragment = ItemlistFragment.newInstance(getItemId(position));
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
index e9756b467..f1f8be559 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
@@ -1,6 +1,8 @@
package de.danoeh.antennapod.adapter.itunes;
import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
@@ -18,6 +20,7 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
+import de.mfietz.fyydlin.SearchHit;
public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
/**
@@ -42,8 +45,9 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
this.context = context;
}
+ @NonNull
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
+ public View getView(int position, View convertView, @NonNull ViewGroup parent) {
//Current podcast
Podcast podcast = data.get(position);
@@ -66,7 +70,7 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
//Set the title
viewHolder.titleView.setText(podcast.title);
- if(!podcast.feedUrl.contains("itunes.apple.com")) {
+ if(podcast.feedUrl != null && !podcast.feedUrl.contains("itunes.apple.com")) {
viewHolder.urlView.setText(podcast.feedUrl);
viewHolder.urlView.setVisibility(View.VISIBLE);
} else {
@@ -87,35 +91,6 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
}
/**
- * View holder object for the GridView
- */
- class PodcastViewHolder {
-
- /**
- * ImageView holding the Podcast image
- */
- public final ImageView coverView;
-
- /**
- * TextView holding the Podcast title
- */
- public final TextView titleView;
-
- public final TextView urlView;
-
-
- /**
- * Constructor
- * @param view GridView cell
- */
- PodcastViewHolder(View view){
- coverView = (ImageView) view.findViewById(R.id.imgvCover);
- titleView = (TextView) view.findViewById(R.id.txtvTitle);
- urlView = (TextView) view.findViewById(R.id.txtvUrl);
- }
- }
-
- /**
* Represents an individual podcast on the iTunes Store.
*/
public static class Podcast { //TODO: Move this out eventually. Possibly to core.itunes.model
@@ -128,14 +103,16 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
/**
* URL of the podcast image
*/
+ @Nullable
public final String imageUrl;
/**
* URL of the podcast feed
*/
+ @Nullable
public final String feedUrl;
- private Podcast(String title, String imageUrl, String feedUrl) {
+ private Podcast(String title, @Nullable String imageUrl, @Nullable String feedUrl) {
this.title = title;
this.imageUrl = imageUrl;
this.feedUrl = feedUrl;
@@ -148,12 +125,16 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
* @throws JSONException
*/
public static Podcast fromSearch(JSONObject json) throws JSONException {
- String title = json.getString("collectionName");
- String imageUrl = json.getString("artworkUrl100");
- String feedUrl = json.getString("feedUrl");
+ String title = json.optString("collectionName", "");
+ String imageUrl = json.optString("artworkUrl100", null);
+ String feedUrl = json.optString("feedUrl", null);
return new Podcast(title, imageUrl, feedUrl);
}
+ public static Podcast fromSearch(SearchHit searchHit) {
+ return new Podcast(searchHit.getTitle(), searchHit.getImageUrl(), searchHit.getXmlUrl());
+ }
+
/**
* Constructs a Podcast instance from iTunes toplist entry
*
@@ -177,4 +158,33 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
}
}
+
+ /**
+ * View holder object for the GridView
+ */
+ class PodcastViewHolder {
+
+ /**
+ * ImageView holding the Podcast image
+ */
+ final ImageView coverView;
+
+ /**
+ * TextView holding the Podcast title
+ */
+ final TextView titleView;
+
+ final TextView urlView;
+
+
+ /**
+ * Constructor
+ * @param view GridView cell
+ */
+ PodcastViewHolder(View view){
+ coverView = (ImageView) view.findViewById(R.id.imgvCover);
+ titleView = (TextView) view.findViewById(R.id.txtvTitle);
+ urlView = (TextView) view.findViewById(R.id.txtvUrl);
+ }
+ }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java
new file mode 100644
index 000000000..192df8ca5
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java
@@ -0,0 +1,65 @@
+package de.danoeh.antennapod.asynctask;
+
+import android.support.annotation.NonNull;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+import de.danoeh.antennapod.core.export.ExportWriter;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.util.LangUtils;
+import rx.Observable;
+
+/**
+ * Writes an OPML file into the export directory in the background.
+ */
+public class ExportWorker {
+
+ private static final String EXPORT_DIR = "export/";
+ private static final String TAG = "ExportWorker";
+ private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds";
+
+ private ExportWriter exportWriter;
+ private File output;
+
+ public ExportWorker(ExportWriter exportWriter) {
+ this(exportWriter, new File(UserPreferences.getDataFolder(EXPORT_DIR),
+ DEFAULT_OUTPUT_NAME + "." + exportWriter.fileExtension()));
+ }
+
+ public ExportWorker(ExportWriter exportWriter, @NonNull File output) {
+ this.exportWriter = exportWriter;
+ this.output = output;
+ }
+
+ public Observable<File> exportObservable() {
+ if (output.exists()) {
+ Log.w(TAG, "Overwriting previously exported file.");
+ output.delete();
+ }
+ return Observable.create(subscriber -> {
+ OutputStreamWriter writer = null;
+ try {
+ writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8);
+ exportWriter.writeDocument(DBReader.getFeedList(), writer);
+ subscriber.onNext(output);
+ } catch (IOException e) {
+ subscriber.onError(e);
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ subscriber.onError(e);
+ }
+ }
+ subscriber.onCompleted();
+ }
+ });
+ }
+
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
deleted file mode 100644
index 13abb26ea..000000000
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.annotation.SuppressLint;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.support.v7.app.AlertDialog;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-
-import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.opml.OpmlWriter;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.storage.DBReader;
-import de.danoeh.antennapod.core.util.LangUtils;
-
-/**
- * Writes an OPML file into the export directory in the background.
- */
-public class OpmlExportWorker extends AsyncTask<Void, Void, Void> {
- private static final String TAG = "OpmlExportWorker";
- private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds.opml";
- public static final String EXPORT_DIR = "export/";
-
- private Context context;
- private File output;
-
- private ProgressDialog progDialog;
- private Exception exception;
-
- public OpmlExportWorker(Context context, File output) {
- this.context = context;
- this.output = output;
- }
-
- public OpmlExportWorker(Context context) {
- this.context = context;
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- OpmlWriter opmlWriter = new OpmlWriter();
- if (output == null) {
- output = new File(
- UserPreferences.getDataFolder(EXPORT_DIR),
- DEFAULT_OUTPUT_NAME);
- if (output.exists()) {
- Log.w(TAG, "Overwriting previously exported file.");
- output.delete();
- }
- }
- OutputStreamWriter writer = null;
- try {
- writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8);
- opmlWriter.writeDocument(DBReader.getFeedList(), writer);
- } catch (IOException e) {
- e.printStackTrace();
- exception = e;
- } finally {
- if (writer != null) {
- try {
- writer.close();
- } catch (IOException ioe) {
- exception = ioe;
- }
- }
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- progDialog.dismiss();
- AlertDialog.Builder alert = new AlertDialog.Builder(context)
- .setNeutralButton(android.R.string.ok,
- (dialog, which) -> dialog.dismiss());
- if (exception != null) {
- alert.setTitle(R.string.export_error_label);
- alert.setMessage(exception.getMessage());
- } else {
- alert.setTitle(R.string.opml_export_success_title);
- alert.setMessage(context
- .getString(R.string.opml_export_success_sum)
- + output.toString())
- .setPositiveButton(R.string.send_label, (dialog, which) -> {
- Uri outputUri = Uri.fromFile(output);
- Intent sendIntent = new Intent(Intent.ACTION_SEND);
- sendIntent.putExtra(Intent.EXTRA_SUBJECT,
- context.getResources().getText(R.string.opml_export_label));
- sendIntent.putExtra(Intent.EXTRA_STREAM, outputUri);
- sendIntent.setType("text/plain");
- context.startActivity(Intent.createChooser(sendIntent,
- context.getResources().getText(R.string.send_label)));
- });
- }
- alert.create().show();
- }
-
- @Override
- protected void onPreExecute() {
- progDialog = new ProgressDialog(context);
- progDialog.setMessage(context.getString(R.string.exporting_label));
- progDialog.setIndeterminate(true);
- progDialog.show();
- }
-
- @SuppressLint("NewApi")
- public void executeAsync() {
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- executeOnExecutor(THREAD_POOL_EXECUTOR);
- } else {
- execute();
- }
- }
-
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
index 1cb653f01..4449d82c2 100644
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
@@ -9,8 +9,8 @@ import java.util.Arrays;
import de.danoeh.antennapod.activity.OpmlImportHolder;
import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.export.opml.OpmlElement;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.opml.OpmlElement;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
index 45ec6c5fa..62ea85811 100644
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
@@ -14,8 +14,8 @@ import java.io.Reader;
import java.util.ArrayList;
import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.opml.OpmlElement;
-import de.danoeh.antennapod.core.opml.OpmlReader;
+import de.danoeh.antennapod.core.export.opml.OpmlElement;
+import de.danoeh.antennapod.core.export.opml.OpmlReader;
public class OpmlImportWorker extends
AsyncTask<Void, Void, ArrayList<OpmlElement>> {
@@ -75,9 +75,7 @@ public class OpmlImportWorker extends
alert.setTitle(R.string.error_label);
alert.setMessage(context.getString(R.string.opml_reader_error)
+ exception.getMessage());
- alert.setNeutralButton(android.R.string.ok, (dialog, which) -> {
- dialog.dismiss();
- });
+ alert.setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss());
alert.create().show();
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java
index 691eccdd9..538abd4c7 100644
--- a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java
+++ b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java
@@ -18,5 +18,6 @@ public class ClientConfigurator {
ClientConfig.playbackServiceCallbacks = new PlaybackServiceCallbacksImpl();
ClientConfig.flattrCallbacks = new FlattrCallbacksImpl();
ClientConfig.dbTasksCallbacks = new DBTasksCallbacksImpl();
+ ClientConfig.castCallbacks = new CastCallbackImpl();
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
index 577a3ecbe..ac073141d 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
@@ -225,6 +225,10 @@ public class EpisodesApplyActionFragment extends Fragment {
checkQueued(false);
resId = R.string.selected_not_queued_label;
break;
+ case R.id.check_has_media:
+ checkWithMedia();
+ resId = R.string.selected_has_media_label;
+ break;
case R.id.sort_title_a_z:
sortByTitle(false);
return true;
@@ -357,6 +361,17 @@ public class EpisodesApplyActionFragment extends Fragment {
refreshCheckboxes();
}
+ private void checkWithMedia() {
+ for (FeedItem episode : episodes) {
+ if(episode.hasMedia()) {
+ checkedIds.add(episode.getId());
+ } else {
+ checkedIds.remove(episode.getId());
+ }
+ }
+ refreshCheckboxes();
+ }
+
private void refreshTitles() {
titles.clear();
for(FeedItem episode : episodes) {
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java
index b875eaf62..a4e71c249 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java
@@ -35,9 +35,7 @@ public class GpodnetSetHostnameDialog {
}
dialog1.dismiss();
})
- .setNegativeButton(R.string.cancel_label, (dialog1, which) -> {
- dialog1.cancel();
- })
+ .setNegativeButton(R.string.cancel_label, (dialog1, which) -> dialog1.cancel())
.setNeutralButton(R.string.pref_gpodnet_sethostname_use_default_host, (dialog1, which) -> {
GpodnetPreferences.setHostname(GpodnetService.DEFAULT_BASE_HOST);
dialog1.dismiss();
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
index 98a4b5356..0bd75b5b0 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
@@ -18,10 +18,6 @@ import android.widget.TextView;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.afollestad.materialdialogs.internal.MDButton;
-import com.squareup.okhttp.Credentials;
-import com.squareup.okhttp.OkHttpClient;
-import com.squareup.okhttp.Request;
-import com.squareup.okhttp.Response;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -33,6 +29,10 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
import de.danoeh.antennapod.core.service.download.ProxyConfig;
+import okhttp3.Credentials;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
@@ -258,10 +258,11 @@ public class ProxyDialog {
SocketAddress address = InetSocketAddress.createUnresolved(host, portValue);
Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase());
Proxy proxy = new Proxy(proxyType, address);
- OkHttpClient client = AntennapodHttpClient.newHttpClient();
- client.setConnectTimeout(10, TimeUnit.SECONDS);
- client.setProxy(proxy);
- client.interceptors().clear();
+ OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder()
+ .connectTimeout(10, TimeUnit.SECONDS)
+ .proxy(proxy);
+ builder.interceptors().clear();
+ OkHttpClient client = builder.build();
if(!TextUtils.isEmpty(username)) {
String credentials = Credentials.basic(username, password);
client.interceptors().add(chain -> {
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java
new file mode 100644
index 000000000..31a544582
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java
@@ -0,0 +1,44 @@
+package de.danoeh.antennapod.dialog;
+
+import android.app.Activity;
+import android.text.InputType;
+
+import com.afollestad.materialdialogs.MaterialDialog;
+
+import java.lang.ref.WeakReference;
+
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.storage.DBWriter;
+
+public class RenameFeedDialog {
+
+ private final WeakReference<Activity> activityRef;
+ private final Feed feed;
+
+ public RenameFeedDialog(Activity activity, Feed feed) {
+ this.activityRef = new WeakReference<>(activity);
+ this.feed = feed;
+ }
+
+ public void show() {
+ Activity activity = activityRef.get();
+ if(activity == null) {
+ return;
+ }
+ new MaterialDialog.Builder(activity)
+ .title(de.danoeh.antennapod.core.R.string.rename_feed_label)
+ .inputType(InputType.TYPE_CLASS_TEXT)
+ .input(feed.getTitle(), feed.getTitle(), true, (dialog, input) -> {
+ feed.setCustomTitle(input.toString());
+ DBWriter.setFeedCustomTitle(feed);
+ dialog.dismiss();
+ })
+ .neutralText(de.danoeh.antennapod.core.R.string.reset)
+ .onNeutral((dialog, which) -> dialog.getInputEditText().setText(feed.getFeedTitle()))
+ .negativeText(de.danoeh.antennapod.core.R.string.cancel_label)
+ .onNegative((dialog, which) -> dialog.dismiss())
+ .autoDismiss(false)
+ .show();
+ }
+
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java
index 8a13a75d9..7d6a66a54 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java
@@ -1,7 +1,7 @@
package de.danoeh.antennapod.dialog;
import android.content.Context;
-import android.content.SharedPreferences;
+import android.support.design.widget.Snackbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
@@ -9,6 +9,7 @@ import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
+import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
@@ -16,36 +17,27 @@ import android.widget.Toast;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
-import java.util.concurrent.TimeUnit;
-
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.event.MessageEvent;
+import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
+import de.greenrobot.event.EventBus;
public abstract class SleepTimerDialog {
private static final String TAG = SleepTimerDialog.class.getSimpleName();
- private static final int DEFAULT_SPINNER_POSITION = 1;
-
private Context context;
- private String PREF_NAME = "SleepTimerDialog";
- private String PREF_VALUE = "LastValue";
- private String PREF_TIME_UNIT = "LastTimeUnit";
- private String PREF_VIBRATE = "Vibrate";
- private String PREF_SHAKE_TO_RESET = "ShakeToReset";
- private SharedPreferences prefs;
private MaterialDialog dialog;
private EditText etxtTime;
private Spinner spTimeUnit;
private CheckBox cbShakeToReset;
private CheckBox cbVibrate;
+ private CheckBox chAutoEnable;
- private TimeUnit[] units = { TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS };
-
- public SleepTimerDialog(Context context) {
+ protected SleepTimerDialog(Context context) {
this.context = context;
- prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
}
public MaterialDialog createNewDialog() {
@@ -58,7 +50,7 @@ public abstract class SleepTimerDialog {
builder.onPositive((dialog, which) -> {
try {
savePreferences();
- long input = readTimeMillis();
+ long input = SleepTimerPreferences.timerMillis();
onTimerSet(input, cbShakeToReset.isChecked(), cbVibrate.isChecked());
dialog.dismiss();
} catch (NumberFormatException e) {
@@ -75,8 +67,9 @@ public abstract class SleepTimerDialog {
spTimeUnit = (Spinner) view.findViewById(R.id.spTimeUnit);
cbShakeToReset = (CheckBox) view.findViewById(R.id.cbShakeToReset);
cbVibrate = (CheckBox) view.findViewById(R.id.cbVibrate);
+ chAutoEnable = (CheckBox) view.findViewById(R.id.chAutoEnable);
- etxtTime.setText(prefs.getString(PREF_VALUE, "15"));
+ etxtTime.setText(SleepTimerPreferences.lastTimerValue());
etxtTime.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
@@ -104,12 +97,17 @@ public abstract class SleepTimerDialog {
android.R.layout.simple_spinner_item, spinnerContent);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spTimeUnit.setAdapter(spinnerAdapter);
- int selection = prefs.getInt(PREF_TIME_UNIT, DEFAULT_SPINNER_POSITION);
- spTimeUnit.setSelection(selection);
+ spTimeUnit.setSelection(SleepTimerPreferences.lastTimerTimeUnit());
- cbShakeToReset.setChecked(prefs.getBoolean(PREF_SHAKE_TO_RESET, true));
- cbVibrate.setChecked(prefs.getBoolean(PREF_VIBRATE, true));
+ cbShakeToReset.setChecked(SleepTimerPreferences.shakeToReset());
+ cbVibrate.setChecked(SleepTimerPreferences.vibrate());
+ chAutoEnable.setChecked(SleepTimerPreferences.autoEnable());
+ chAutoEnable.setOnCheckedChangeListener((compoundButton, isChecked) -> {
+ SleepTimerPreferences.setAutoEnable(isChecked);
+ int messageString = isChecked ? R.string.sleep_timer_enabled_label : R.string.sleep_timer_disabled_label;
+ EventBus.getDefault().post(new MessageEvent(context.getString(messageString)));
+ });
return dialog;
}
@@ -125,19 +123,12 @@ public abstract class SleepTimerDialog {
public abstract void onTimerSet(long millis, boolean shakeToReset, boolean vibrate);
- private long readTimeMillis() {
- TimeUnit selectedUnit = units[spTimeUnit.getSelectedItemPosition()];
- long value = Long.parseLong(etxtTime.getText().toString());
- return selectedUnit.toMillis(value);
- }
-
private void savePreferences() {
- prefs.edit()
- .putString(PREF_VALUE, etxtTime.getText().toString())
- .putInt(PREF_TIME_UNIT, spTimeUnit.getSelectedItemPosition())
- .putBoolean(PREF_SHAKE_TO_RESET, cbShakeToReset.isChecked())
- .putBoolean(PREF_VIBRATE, cbVibrate.isChecked())
- .apply();
+ SleepTimerPreferences.setLastTimer(etxtTime.getText().toString(),
+ spTimeUnit.getSelectedItemPosition());
+ SleepTimerPreferences.setShakeToReset(cbShakeToReset.isChecked());
+ SleepTimerPreferences.setVibrate(cbVibrate.isChecked());
+ SleepTimerPreferences.setAutoEnable(chAutoEnable.isChecked());
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
index 2bf9c4e7a..6a975fe49 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
@@ -95,9 +95,7 @@ public class VariableSpeedDialog {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.set_playback_speed_label);
builder.setMultiChoiceItems(R.array.playback_speed_values,
- speedChecked, (dialog, which, isChecked) -> {
- speedChecked[which] = isChecked;
- });
+ speedChecked, (dialog, which, isChecked) -> speedChecked[which] = isChecked);
builder.setNegativeButton(android.R.string.cancel, null);
builder.setPositiveButton(android.R.string.ok,
(dialog, which) -> {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
index 45364ca07..f14ebbdaf 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
@@ -39,10 +39,11 @@ public class AddFeedFragment extends Fragment {
etxtFeedurl.setText(args.getString(ARG_FEED_URL));
}
+ Button butSearchITunes = (Button) root.findViewById(R.id.butSearchItunes);
Button butBrowserGpoddernet = (Button) root.findViewById(R.id.butBrowseGpoddernet);
+ Button butSearchFyyd = (Button) root.findViewById(R.id.butSearchFyyd);
Button butOpmlImport = (Button) root.findViewById(R.id.butOpmlImport);
Button butConfirm = (Button) root.findViewById(R.id.butConfirm);
- Button butSearchITunes = (Button) root.findViewById(R.id.butSearchItunes);
final MainActivity activity = (MainActivity) getActivity();
activity.getSupportActionBar().setTitle(R.string.add_feed_label);
@@ -51,6 +52,8 @@ public class AddFeedFragment extends Fragment {
butBrowserGpoddernet.setOnClickListener(v -> activity.loadChildFragment(new GpodnetMainFragment()));
+ butSearchFyyd.setOnClickListener(v -> activity.loadChildFragment(new FyydSearchFragment()));
+
butOpmlImport.setOnClickListener(v -> startActivity(new Intent(getActivity(),
OpmlImportFromPathActivity.class)));
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
index 8ae7f1cf9..bbfd1688d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -80,6 +80,7 @@ public class AllEpisodesFragment extends Fragment {
private boolean viewsCreated = false;
private boolean isUpdatingFeeds;
+ protected boolean isMenuInvalidationAllowed = false;
protected Subscription subscription;
private LinearLayoutManager layoutManager;
@@ -180,7 +181,7 @@ public class AllEpisodesFragment extends Fragment {
}
super.onCreateOptionsMenu(menu, inflater);
if (itemsLoaded) {
- inflater.inflate(R.menu.new_episodes, menu);
+ inflater.inflate(R.menu.episodes, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
@@ -206,11 +207,13 @@ public class AllEpisodesFragment extends Fragment {
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- if (itemsLoaded) {
- MenuItem menuItem = menu.findItem(R.id.mark_all_read_item);
- if (menuItem != null) {
- menuItem.setVisible(episodes != null && !episodes.isEmpty());
- }
+ MenuItem markAllRead = menu.findItem(R.id.mark_all_read_item);
+ if (markAllRead != null) {
+ markAllRead.setVisible(!showOnlyNewEpisodes() && episodes != null && !episodes.isEmpty());
+ }
+ MenuItem markAllSeen = menu.findItem(R.id.mark_all_seen_item);
+ if(markAllSeen != null) {
+ markAllSeen.setVisible(showOnlyNewEpisodes() && episodes != null && !episodes.isEmpty());
}
}
@@ -225,19 +228,32 @@ public class AllEpisodesFragment extends Fragment {
}
return true;
case R.id.mark_all_read_item:
- ConfirmationDialog conDialog = new ConfirmationDialog(getActivity(),
+ ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(getActivity(),
R.string.mark_all_read_label,
R.string.mark_all_read_confirmation_msg) {
@Override
- public void onConfirmButtonPressed(
- DialogInterface dialog) {
+ public void onConfirmButtonPressed(DialogInterface dialog) {
dialog.dismiss();
DBWriter.markAllItemsRead();
Toast.makeText(getActivity(), R.string.mark_all_read_msg, Toast.LENGTH_SHORT).show();
}
};
- conDialog.createNewDialog().show();
+ markAllReadConfirmationDialog.createNewDialog().show();
+ return true;
+ case R.id.mark_all_seen_item:
+ ConfirmationDialog markAllSeenConfirmationDialog = new ConfirmationDialog(getActivity(),
+ R.string.mark_all_seen_label,
+ R.string.mark_all_seen_confirmation_msg) {
+
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+ DBWriter.markNewItemsSeen();
+ Toast.makeText(getActivity(), R.string.mark_all_seen_msg, Toast.LENGTH_SHORT).show();
+ }
+ };
+ markAllSeenConfirmationDialog.createNewDialog().show();
return true;
default:
return false;
@@ -378,6 +394,20 @@ public class AllEpisodesFragment extends Fragment {
return item != null && item.isTagged(FeedItem.TAG_QUEUE);
}
+ @Override
+ public LongList getQueueIds() {
+ LongList queueIds = new LongList();
+ if(episodes == null) {
+ return queueIds;
+ }
+ for(FeedItem item : episodes) {
+ if(item.isTagged(FeedItem.TAG_QUEUE)) {
+ queueIds.add(item.getId());
+ }
+ }
+ return queueIds;
+ }
+
};
public void onEventMainThread(FeedItemEvent event) {
@@ -401,7 +431,7 @@ public class AllEpisodesFragment extends Fragment {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update;
downloaderList = update.downloaders;
- if (isUpdatingFeeds != update.feedIds.length > 0) {
+ if (isMenuInvalidationAllowed && isUpdatingFeeds != update.feedIds.length > 0) {
getActivity().supportInvalidateOptionsMenu();
}
if(listAdapter != null && update.mediaIds.length > 0) {
@@ -450,9 +480,7 @@ public class AllEpisodesFragment extends Fragment {
onFragmentLoaded();
}
}
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
protected List<FeedItem> loadData() {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
index 77e66f3b0..4d34d076d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
@@ -69,16 +69,18 @@ public class ChaptersFragment extends ListFragment implements MediaplayerInfoCon
@Override
public void onMediaChanged(Playable media) {
- if(this.media == media || adapter == null) {
+ if(this.media == media) {
return;
}
this.media = media;
- adapter.setMedia(media);
- adapter.notifyDataSetChanged();
- if(media == null || media.getChapters() == null || media.getChapters().size() == 0) {
- setEmptyText(getString(R.string.no_items_label));
- } else {
- setEmptyText(null);
+ if (adapter != null) {
+ adapter.setMedia(media);
+ adapter.notifyDataSetChanged();
+ if(media == null || media.getChapters() == null || media.getChapters().size() == 0) {
+ setEmptyText(getString(R.string.no_items_label));
+ } else {
+ setEmptyText(null);
+ }
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
index d14265f70..1ba7ed557 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
@@ -215,9 +215,7 @@ public class CompletedDownloadsFragment extends ListFragment {
onFragmentLoaded();
}
}
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
index 943ddeec7..1d3fcefba 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
@@ -33,22 +33,15 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra
public static CoverFragment newInstance(Playable item) {
CoverFragment f = new CoverFragment();
- if (item != null) {
- Bundle args = new Bundle();
- args.putParcelable(ARG_PLAYABLE, item);
- f.setArguments(args);
- }
+ f.media = item;
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Bundle args = getArguments();
- if (args != null) {
- media = args.getParcelable(ARG_PLAYABLE);
- } else {
- Log.e(TAG, TAG + " was called with invalid arguments");
+ if (media == null) {
+ Log.e(TAG, TAG + " was called without media");
}
}
@@ -67,7 +60,7 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra
txtvPodcastTitle.setText(media.getFeedTitle());
txtvEpisodeTitle.setText(media.getEpisodeTitle());
Glide.with(this)
- .load(media.getImageUri())
+ .load(media.getImageLocation())
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.dontAnimate()
.fitCenter()
@@ -98,11 +91,13 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra
@Override
public void onMediaChanged(Playable media) {
- if(!isAdded() || this.media == media) {
+ if(this.media == media) {
return;
}
this.media = media;
- loadMediaInfo();
+ if (isAdded()) {
+ loadMediaInfo();
+ }
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
index 93527b149..0a710196a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
@@ -165,9 +165,7 @@ public class DownloadLogFragment extends ListFragment {
onFragmentLoaded();
}
}
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
index f23981935..e2fbd91f3 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
@@ -79,6 +79,11 @@ public class EpisodesFragment extends Fragment {
public static class EpisodesPagerAdapter extends FragmentPagerAdapter {
private final Resources resources;
+ private AllEpisodesFragment[] fragments = {
+ new NewEpisodesFragment(),
+ new AllEpisodesFragment(),
+ new FavoriteEpisodesFragment()
+ };
public EpisodesPagerAdapter(FragmentManager fm, Resources resources) {
super(fm);
@@ -87,15 +92,7 @@ public class EpisodesFragment extends Fragment {
@Override
public Fragment getItem(int position) {
- switch (position) {
- case POS_ALL_EPISODES:
- return new AllEpisodesFragment();
- case POS_NEW_EPISODES:
- return new NewEpisodesFragment();
- case POS_FAV_EPISODES:
- return new FavoriteEpisodesFragment();
- }
- return null;
+ return fragments[position];
}
@Override
@@ -116,5 +113,14 @@ public class EpisodesFragment extends Fragment {
return super.getPageTitle(position);
}
}
+
+ @Override
+ public void setPrimaryItem(ViewGroup container, int position, Object object) {
+ super.setPrimaryItem(container, position, object);
+ for (int i = 0; i < TOTAL_COUNT; i++) {
+ // Invalidating the OptionsMenu is only allowed for the currently active fragment
+ fragments[i].isMenuInvalidationAllowed = (i == position);
+ }
+ }
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
index 758f8095d..1e385728a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
@@ -163,7 +163,7 @@ public class ExternalPlayerFragment extends Fragment {
((double) controller.getPosition() / controller.getDuration() * 100));
Glide.with(getActivity())
- .load(media.getImageUri())
+ .load(media.getImageLocation())
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
index 65305df3d..234c8377d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
@@ -71,9 +71,7 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
Snackbar snackbar = Snackbar.make(root, getString(R.string.removed_item),
Snackbar.LENGTH_LONG);
- snackbar.setAction(getString(R.string.undo), v -> {
- DBWriter.addFavoriteItem(item);
- });
+ snackbar.setAction(getString(R.string.undo), v -> DBWriter.addFavoriteItem(item));
snackbar.show();
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java
new file mode 100644
index 000000000..7c1ec5ec1
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java
@@ -0,0 +1,192 @@
+package de.danoeh.antennapod.fragment;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.widget.SearchView;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.GridView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
+import de.danoeh.antennapod.adapter.itunes.ItunesAdapter;
+import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
+import de.danoeh.antennapod.menuhandler.MenuItemUtils;
+import de.mfietz.fyydlin.FyydClient;
+import de.mfietz.fyydlin.FyydResponse;
+import de.mfietz.fyydlin.SearchHit;
+import rx.Subscription;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
+
+import static de.danoeh.antennapod.adapter.itunes.ItunesAdapter.Podcast;
+import static java.util.Collections.emptyList;
+
+public class FyydSearchFragment extends Fragment {
+
+ private static final String TAG = "FyydSearchFragment";
+
+ /**
+ * Adapter responsible with the search results
+ */
+ private ItunesAdapter adapter;
+ private GridView gridView;
+ private ProgressBar progressBar;
+ private TextView txtvError;
+ private Button butRetry;
+ private TextView txtvEmpty;
+
+ private FyydClient client = new FyydClient(AntennapodHttpClient.getHttpClient());
+
+ /**
+ * List of podcasts retreived from the search
+ */
+ private List<Podcast> searchResults;
+ private Subscription subscription;
+
+ /**
+ * Constructor
+ */
+ public FyydSearchFragment() {
+ // Required empty public constructor
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ // Inflate the layout for this fragment
+ View root = inflater.inflate(R.layout.fragment_itunes_search, container, false);
+ gridView = (GridView) root.findViewById(R.id.gridView);
+ adapter = new ItunesAdapter(getActivity(), new ArrayList<>());
+ gridView.setAdapter(adapter);
+
+ //Show information about the podcast when the list item is clicked
+ gridView.setOnItemClickListener((parent, view1, position, id) -> {
+ Podcast podcast = searchResults.get(position);
+ Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);
+ intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, podcast.feedUrl);
+ intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, podcast.title);
+ startActivity(intent);
+ });
+ progressBar = (ProgressBar) root.findViewById(R.id.progressBar);
+ txtvError = (TextView) root.findViewById(R.id.txtvError);
+ butRetry = (Button) root.findViewById(R.id.butRetry);
+ txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
+
+ return root;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (subscription != null) {
+ subscription.unsubscribe();
+ }
+ adapter = null;
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.itunes_search, menu);
+ MenuItem searchItem = menu.findItem(R.id.action_search);
+ final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
+ MenuItemUtils.adjustTextColor(getActivity(), sv);
+ sv.setQueryHint(getString(R.string.search_fyyd_label));
+ sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String s) {
+ sv.clearFocus();
+ search(s);
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String s) {
+ return false;
+ }
+ });
+ MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ return true;
+ }
+
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ getActivity().getSupportFragmentManager().popBackStack();
+ return true;
+ }
+ });
+ MenuItemCompat.expandActionView(searchItem);
+ }
+
+ private void search(String query) {
+ if (subscription != null) {
+ subscription.unsubscribe();
+ }
+ showOnlyProgressBar();
+ subscription = client.searchPodcasts(query)
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> {
+ progressBar.setVisibility(View.GONE);
+ processSearchResult(result);
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ progressBar.setVisibility(View.GONE);
+ txtvError.setText(error.toString());
+ txtvError.setVisibility(View.VISIBLE);
+ butRetry.setOnClickListener(v -> search(query));
+ butRetry.setVisibility(View.VISIBLE);
+ });
+ }
+
+ private void showOnlyProgressBar() {
+ gridView.setVisibility(View.GONE);
+ txtvError.setVisibility(View.GONE);
+ butRetry.setVisibility(View.GONE);
+ txtvEmpty.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
+ }
+
+ void processSearchResult(FyydResponse response) {
+ adapter.clear();
+ if (!response.getData().isEmpty()) {
+ adapter.clear();
+ searchResults = new ArrayList<>();
+ for (SearchHit searchHit : response.getData().values()) {
+ Podcast podcast = Podcast.fromSearch(searchHit);
+ searchResults.add(podcast);
+ }
+ } else {
+ searchResults = emptyList();
+ }
+ for(Podcast podcast : searchResults) {
+ adapter.add(podcast);
+ }
+ adapter.notifyDataSetInvalidated();
+ gridView.setVisibility(!searchResults.isEmpty() ? View.VISIBLE : View.GONE);
+ txtvEmpty.setVisibility(searchResults.isEmpty() ? View.VISIBLE : View.GONE);
+ }
+
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
index 55d28cadb..a0586fe16 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
@@ -185,8 +185,10 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
super.onViewCreated(view, savedInstanceState);
Bundle args = getArguments();
if (args.containsKey(ARG_PLAYABLE)) {
- media = args.getParcelable(ARG_PLAYABLE);
- shownotesProvider = media;
+ if (media == null) {
+ media = args.getParcelable(ARG_PLAYABLE);
+ shownotesProvider = media;
+ }
load();
} else if (args.containsKey(ARG_FEEDITEM_ID)) {
long id = getArguments().getLong(ARG_FEEDITEM_ID);
@@ -196,9 +198,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
.subscribe(feedItem -> {
shownotesProvider = feedItem;
load();
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
}
@@ -311,9 +311,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
webvDescription.loadDataWithBaseURL(null, data, "text/html",
"utf-8", "about:blank");
Log.d(TAG, "Webview loaded");
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
private String loadData() {
@@ -348,7 +346,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
}
private boolean restoreFromPreference() {
- if (!saveState) {
+ if (saveState) {
Log.d(TAG, "Restoring from preferences");
Activity activity = getActivity();
if (activity != null) {
@@ -381,12 +379,14 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
@Override
public void onMediaChanged(Playable media) {
- if(this.media == media || webvDescription == null) {
+ if(this.media == media) {
return;
}
this.media = media;
this.shownotesProvider = media;
- load();
+ if (webvDescription != null) {
+ load();
+ }
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
index e721af47d..7939dcb23 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
@@ -44,9 +44,7 @@ import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
-import de.danoeh.antennapod.core.event.FavoritesEvent;
import de.danoeh.antennapod.core.event.FeedItemEvent;
-import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
@@ -60,7 +58,9 @@ import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.DateUtils;
+import de.danoeh.antennapod.core.util.Flavors;
import de.danoeh.antennapod.core.util.IntentUtils;
+import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.playback.Timeline;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
@@ -222,7 +222,8 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
return;
}
DefaultActionButtonCallback actionButtonCallback = new DefaultActionButtonCallback(getActivity());
- actionButtonCallback.onActionButtonPressed(item);
+ actionButtonCallback.onActionButtonPressed(item, item.isTagged(FeedItem.TAG_QUEUE) ?
+ LongList.of(item.getId()) : new LongList(0));
FeedMedia media = item.getMedia();
if (media != null && media.isDownloaded()) {
// playback was started, dialog should close itself
@@ -312,7 +313,10 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
if(!isAdded() || item == null) {
return;
}
- ((CastEnabledActivity) getActivity()).requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ super.onCreateOptionsMenu(menu, inflater);
+ if (Flavors.FLAVOR == Flavors.PLAY) {
+ ((CastEnabledActivity) getActivity()).requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ }
inflater.inflate(R.menu.feeditem_options, menu);
popupMenu = menu;
if (item.hasMedia()) {
@@ -374,7 +378,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
}
Glide.with(getActivity())
- .load(item.getImageUri())
+ .load(item.getImageLocation())
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
@@ -417,7 +421,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
butAction2Text = R.string.stream_label;
} else {
butAction2Icon = "{md-delete 24sp}";
- butAction2Text = R.string.remove_label;
+ butAction2Text = R.string.delete_label;
}
if (isDownloading) {
butAction1Icon = "{md-cancel 24sp}";
@@ -576,9 +580,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
item = result;
itemsLoaded = true;
onFragmentLoaded();
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
private FeedItem loadInBackground() {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
index 3194d7cab..a118673a6 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
@@ -64,8 +64,10 @@ import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil;
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
+import de.danoeh.antennapod.dialog.RenameFeedDialog;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
@@ -98,6 +100,7 @@ public class ItemlistFragment extends ListFragment {
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
+ private boolean headerCreated = false;
private List<Downloader> downloaderList;
@@ -105,7 +108,10 @@ public class ItemlistFragment extends ListFragment {
private boolean isUpdatingFeed;
+ private TextView txtvTitle;
private IconTextView txtvFailure;
+ private ImageView imgvBackground;
+ private ImageView imgvCover;
private TextView txtvInformation;
@@ -247,6 +253,9 @@ public class ItemlistFragment extends ListFragment {
.newInstance(feed.getItems());
((MainActivity)getActivity()).loadChildFragment(fragment);
return true;
+ case R.id.rename_item:
+ new RenameFeedDialog(getActivity(), feed).show();
+ return true;
case R.id.remove_item:
final FeedRemover remover = new FeedRemover(
getActivity(), feed) {
@@ -258,7 +267,7 @@ public class ItemlistFragment extends ListFragment {
};
ConfirmationDialog conDialog = new ConfirmationDialog(getActivity(),
R.string.remove_feed_label,
- R.string.feed_delete_confirmation_msg) {
+ getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
@Override
public void onConfirmButtonPressed(
@@ -414,6 +423,7 @@ public class ItemlistFragment extends ListFragment {
public void update(EventDistributor eventDistributor, Integer arg) {
if ((EVENTS & arg) != 0) {
Log.d(TAG, "Received contentUpdate Intent. arg " + arg);
+ refreshHeaderView();
loadItems();
updateProgressBarVisibility();
}
@@ -459,15 +469,17 @@ public class ItemlistFragment extends ListFragment {
}
private void refreshHeaderView() {
- if (getListView() == null || feed == null) {
- Log.e(TAG, "Unable to setup listview: recyclerView = null or feed = null");
+ if (getListView() == null || feed == null || !headerCreated) {
+ Log.e(TAG, "Unable to refresh header view");
return;
}
+ loadFeedImage();
if(feed.hasLastUpdateFailed()) {
txtvFailure.setVisibility(View.VISIBLE);
} else {
txtvFailure.setVisibility(View.GONE);
}
+ txtvTitle.setText(feed.getTitle());
if(feed.getItemFilter() != null) {
FeedItemFilter filter = feed.getItemFilter();
if(filter.getValues().length > 0) {
@@ -497,10 +509,10 @@ public class ItemlistFragment extends ListFragment {
View header = inflater.inflate(R.layout.feeditemlist_header, lv, false);
lv.addHeaderView(header);
- TextView txtvTitle = (TextView) header.findViewById(R.id.txtvTitle);
+ txtvTitle = (TextView) header.findViewById(R.id.txtvTitle);
TextView txtvAuthor = (TextView) header.findViewById(R.id.txtvAuthor);
- ImageView imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground);
- ImageView imgvCover = (ImageView) header.findViewById(R.id.imgvCover);
+ imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground);
+ imgvCover = (ImageView) header.findViewById(R.id.imgvCover);
ImageButton butShowInfo = (ImageButton) header.findViewById(R.id.butShowInfo);
txtvInformation = (TextView) header.findViewById(R.id.txtvInformation);
txtvFailure = (IconTextView) header.findViewById(R.id.txtvFailure);
@@ -512,8 +524,22 @@ public class ItemlistFragment extends ListFragment {
// https://github.com/bumptech/glide/issues/529
imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
+ loadFeedImage();
+
+ butShowInfo.setOnClickListener(v -> {
+ if (viewsCreated && itemsLoaded) {
+ Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class);
+ startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID,
+ feed.getId());
+ startActivity(startIntent);
+ }
+ });
+ headerCreated = true;
+ }
+
+ private void loadFeedImage() {
Glide.with(getActivity())
- .load(feed.getImageUri())
+ .load(feed.getImageLocation())
.placeholder(R.color.image_readability_tint)
.error(R.color.image_readability_tint)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
@@ -522,22 +548,13 @@ public class ItemlistFragment extends ListFragment {
.into(imgvBackground);
Glide.with(getActivity())
- .load(feed.getImageUri())
+ .load(feed.getImageLocation())
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
.dontAnimate()
.into(imgvCover);
-
- butShowInfo.setOnClickListener(v -> {
- if (viewsCreated && itemsLoaded) {
- Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class);
- startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID,
- feed.getId());
- startActivity(startIntent);
- }
- });
}
@@ -578,6 +595,20 @@ public class ItemlistFragment extends ListFragment {
}
@Override
+ public LongList getQueueIds() {
+ LongList queueIds = new LongList();
+ if(feed == null) {
+ return queueIds;
+ }
+ for(FeedItem item : feed.getItems()) {
+ if(item.isTagged(FeedItem.TAG_QUEUE)) {
+ queueIds.add(item.getId());
+ }
+ }
+ return queueIds;
+ }
+
+ @Override
public int getCount() {
return (feed != null) ? feed.getNumOfItems() : 0;
}
@@ -612,9 +643,7 @@ public class ItemlistFragment extends ListFragment {
onFragmentLoaded();
}
}
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
private Feed loadData() {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
index b736688b9..db88c070d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
@@ -18,9 +18,6 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import com.afollestad.materialdialogs.MaterialDialog;
-import com.squareup.okhttp.OkHttpClient;
-import com.squareup.okhttp.Request;
-import com.squareup.okhttp.Response;
import org.json.JSONArray;
import org.json.JSONException;
@@ -39,6 +36,9 @@ import de.danoeh.antennapod.adapter.itunes.ItunesAdapter;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
index 7ef070f21..183c10f3d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
@@ -7,6 +7,8 @@ import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
@@ -92,7 +94,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
}
};
- Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_read_label),
+ Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_seen_label),
Snackbar.LENGTH_LONG);
snackbar.setAction(getString(R.string.undo), v -> {
DBWriter.markItemPlayed(FeedItem.NEW, item.getId());
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
index 49c68c732..441f0096c 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
@@ -28,6 +28,7 @@ import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.core.util.LongList;
import de.greenrobot.event.EventBus;
import rx.Observable;
import rx.Subscription;
@@ -251,6 +252,20 @@ public class PlaybackHistoryFragment extends ListFragment {
return null;
}
}
+
+ @Override
+ public LongList getQueueIds() {
+ LongList queueIds = new LongList();
+ if(playbackHistory == null) {
+ return queueIds;
+ }
+ for (FeedItem item : playbackHistory) {
+ if (item.isTagged(FeedItem.TAG_QUEUE)) {
+ queueIds.add(item.getId());
+ }
+ }
+ return queueIds;
+ }
};
private void loadItems() {
@@ -268,9 +283,7 @@ public class PlaybackHistoryFragment extends ListFragment {
onFragmentLoaded();
}
}
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
private List<FeedItem> loadData() {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
index 08e681c99..d7f25c134 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -304,11 +304,11 @@ public class QueueFragment extends Fragment {
};
conDialog.createNewDialog().show();
return true;
- case R.id.queue_sort_alpha_asc:
- QueueSorter.sort(getActivity(), QueueSorter.Rule.ALPHA_ASC, true);
+ case R.id.queue_sort_episode_title_asc:
+ QueueSorter.sort(getActivity(), QueueSorter.Rule.EPISODE_TITLE_ASC, true);
return true;
- case R.id.queue_sort_alpha_desc:
- QueueSorter.sort(getActivity(), QueueSorter.Rule.ALPHA_DESC, true);
+ case R.id.queue_sort_episode_title_desc:
+ QueueSorter.sort(getActivity(), QueueSorter.Rule.EPISODE_TITLE_DESC, true);
return true;
case R.id.queue_sort_date_asc:
QueueSorter.sort(getActivity(), QueueSorter.Rule.DATE_ASC, true);
@@ -322,6 +322,12 @@ public class QueueFragment extends Fragment {
case R.id.queue_sort_duration_desc:
QueueSorter.sort(getActivity(), QueueSorter.Rule.DURATION_DESC, true);
return true;
+ case R.id.queue_sort_feed_title_asc:
+ QueueSorter.sort(getActivity(), QueueSorter.Rule.FEED_TITLE_ASC, true);
+ return true;
+ case R.id.queue_sort_feed_title_desc:
+ QueueSorter.sort(getActivity(), QueueSorter.Rule.FEED_TITLE_DESC, true);
+ return true;
default:
return false;
}
@@ -605,9 +611,7 @@ public class QueueFragment extends Fragment {
recyclerAdapter.notifyDataSetChanged();
}
}
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
index 510909379..f64b4c20a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
@@ -182,6 +182,9 @@ public class SearchFragment extends ListFragment {
}
searchAdapter.notifyDataSetChanged();
setListShown(true);
+
+ String query = getArguments().getString(ARG_QUERY);
+ setEmptyText(getString(R.string.no_results_for_query, query));
}
private final SearchlistAdapter.ItemAccess itemAccess = new SearchlistAdapter.ItemAccess() {
@@ -219,9 +222,7 @@ public class SearchFragment extends ListFragment {
onFragmentLoaded();
}
}
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
private List<SearchResult> performSearch() {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
index a314419ac..9626e6c2e 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
@@ -26,7 +26,9 @@ import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.dialog.RenameFeedDialog;
import rx.Observable;
+import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
@@ -46,6 +48,7 @@ public class SubscriptionFragment extends Fragment {
private int mPosition = -1;
+ private Subscription subscription;
public SubscriptionFragment() {
}
@@ -88,16 +91,25 @@ public class SubscriptionFragment extends Fragment {
EventDistributor.getInstance().register(contentUpdate);
}
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if(subscription != null) {
+ subscription.unsubscribe();
+ }
+ }
+
private void loadSubscriptions() {
- Observable.fromCallable(() -> DBReader.getNavDrawerData())
+ if(subscription != null) {
+ subscription.unsubscribe();
+ }
+ subscription = Observable.fromCallable(DBReader::getNavDrawerData)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
navDrawerData = result;
subscriptionAdapter.notifyDataSetChanged();
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
@Override
@@ -143,21 +155,18 @@ public class SubscriptionFragment extends Fragment {
Observable.fromCallable(() -> DBWriter.markFeedSeen(feed.getId()))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(result -> {
- loadSubscriptions();
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ .subscribe(result -> loadSubscriptions(),
+ error -> Log.e(TAG, Log.getStackTraceString(error)));
return true;
case R.id.mark_all_read_item:
Observable.fromCallable(() -> DBWriter.markFeedRead(feed.getId()))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(result -> {
- loadSubscriptions();
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
+ .subscribe(result -> loadSubscriptions(),
+ error -> Log.e(TAG, Log.getStackTraceString(error)));
+ return true;
+ case R.id.rename_item:
+ new RenameFeedDialog(getActivity(), feed).show();
return true;
case R.id.remove_item:
final FeedRemover remover = new FeedRemover(getContext(), feed) {
@@ -169,7 +178,7 @@ public class SubscriptionFragment extends Fragment {
};
ConfirmationDialog conDialog = new ConfirmationDialog(getContext(),
R.string.remove_feed_label,
- R.string.feed_delete_confirmation_msg) {
+ getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
@Override
public void onConfirmButtonPressed(
DialogInterface dialog) {
diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
index b80213459..57b7c359c 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
@@ -80,7 +80,7 @@ public class FeedItemMenuHandler {
if(queueAccess == null || queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == selectedItem.getId()) {
mi.setItemVisibility(R.id.move_to_bottom_item, false);
}
- if (!isInQueue || isPlaying) {
+ if (!isInQueue) {
mi.setItemVisibility(R.id.remove_from_queue_item, false);
}
if (!(!isInQueue && selectedItem.getMedia() != null)) {
@@ -101,6 +101,8 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.share_download_url_with_position_item, false);
}
+ mi.setItemVisibility(R.id.share_file, hasMedia && selectedItem.getMedia().fileExists());
+
if (selectedItem.isPlayed()) {
mi.setItemVisibility(R.id.mark_read_item, false);
} else {
@@ -239,6 +241,9 @@ public class FeedItemMenuHandler {
case R.id.share_download_url_with_position_item:
ShareUtils.shareFeedItemDownloadLink(context, selectedItem, true);
break;
+ case R.id.share_file:
+ ShareUtils.shareFeedItemFile(context, selectedItem.getMedia());
+ break;
default:
Log.d(TAG, "Unknown menuItemId: " + menuItemId);
return false;
diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java
index 4c28b197d..ac703e13e 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java
@@ -28,6 +28,7 @@ public class MenuItemUtils extends de.danoeh.antennapod.core.menuhandler.MenuIte
}
}
+ @SuppressWarnings("ResourceType")
public static void refreshLockItem(Context context, Menu menu) {
final MenuItem queueLock = menu.findItem(de.danoeh.antennapod.R.id.queue_lock);
int[] lockIcons = new int[] { de.danoeh.antennapod.R.attr.ic_lock_open, de.danoeh.antennapod.R.attr.ic_lock_closed };
diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
index 6c03dc7ae..2ca7dd029 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
@@ -3,6 +3,7 @@ package de.danoeh.antennapod.preferences;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
+import android.app.ProgressDialog;
import android.app.TimePickerDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -28,14 +29,13 @@ import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.text.format.DateFormat;
+import android.text.format.DateUtils;
import android.util.Log;
import android.widget.EditText;
-import android.widget.Toast;
import android.widget.ListView;
+import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
-import com.google.android.gms.common.ConnectionResult;
-import com.google.android.gms.common.GoogleApiAvailability;
import org.apache.commons.lang3.ArrayUtils;
@@ -43,6 +43,8 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -52,10 +54,14 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.AboutActivity;
import de.danoeh.antennapod.activity.DirectoryChooserActivity;
import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.activity.MediaplayerActivity;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.activity.PreferenceActivityGingerbread;
import de.danoeh.antennapod.activity.StatisticsActivity;
-import de.danoeh.antennapod.asynctask.OpmlExportWorker;
+import de.danoeh.antennapod.asynctask.ExportWorker;
+import de.danoeh.antennapod.core.export.ExportWriter;
+import de.danoeh.antennapod.core.export.html.HtmlWriter;
+import de.danoeh.antennapod.core.export.opml.OpmlWriter;
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.GpodnetSyncService;
@@ -67,6 +73,10 @@ import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog;
import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog;
import de.danoeh.antennapod.dialog.ProxyDialog;
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
+import rx.Observable;
+import rx.Subscription;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
/**
* Sets up a preference UI that lets the user change user preferences.
@@ -76,35 +86,45 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
private static final String TAG = "PreferenceController";
- public static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings";
- public static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate";
- public static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
- public static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs";
- public static final String PREF_OPML_EXPORT = "prefOpmlExport";
- public static final String STATISTICS = "statistics";
- public static final String PREF_ABOUT = "prefAbout";
- public static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
- public static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
- public static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher";
- public static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate";
- public static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information";
- public static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync";
- public static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout";
- public static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname";
- public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
- public static final String PREF_PROXY = "prefProxy";
- public static final String PREF_KNOWN_ISSUES = "prefKnownIssues";
- public static final String PREF_FAQ = "prefFaq";
- public static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport";
-
- private final PreferenceUI ui;
-
- private CheckBoxPreference[] selectedNetworks;
-
+ private static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings";
+ private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate";
+ private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
+ private static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs";
+ private static final String PREF_OPML_EXPORT = "prefOpmlExport";
+ private static final String PREF_HTML_EXPORT = "prefHtmlExport";
+ private static final String STATISTICS = "statistics";
+ private static final String PREF_ABOUT = "prefAbout";
+ private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
+ private static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
+ private static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher";
+ public static final String PREF_PLAYBACK_REWIND_DELTA_LAUNCHER = "prefPlaybackRewindDeltaLauncher";
+ public static final String PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER = "prefPlaybackFastForwardDeltaLauncher";
+ private static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate";
+ private static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information";
+ private static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync";
+ private static final String PREF_GPODNET_FORCE_FULL_SYNC = "pref_gpodnet_force_full_sync";
+ private static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout";
+ private static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname";
+ private static final String PREF_GPODNET_NOTIFICATIONS = "pref_gpodnet_notifications";
+ private static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
+ private static final String PREF_PROXY = "prefProxy";
+ private static final String PREF_KNOWN_ISSUES = "prefKnownIssues";
+ private static final String PREF_FAQ = "prefFaq";
+ private static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport";
private static final String[] EXTERNAL_STORAGE_PERMISSIONS = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE };
private static final int PERMISSION_REQUEST_EXTERNAL_STORAGE = 41;
+ private final PreferenceUI ui;
+ private final SharedPreferences.OnSharedPreferenceChangeListener gpoddernetListener =
+ (sharedPreferences, key) -> {
+ if (GpodnetPreferences.PREF_LAST_SYNC_ATTEMPT_TIMESTAMP.equals(key)) {
+ updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(),
+ GpodnetPreferences.getLastSyncAttemptTimestamp());
+ }
+ };
+ private CheckBoxPreference[] selectedNetworks;
+ private Subscription subscription;
public PreferenceController(PreferenceUI ui) {
this.ui = ui;
@@ -112,22 +132,12 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
.registerOnSharedPreferenceChangeListener(this);
}
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if(key.equals(UserPreferences.PREF_SONIC)) {
- CheckBoxPreference prefSonic = (CheckBoxPreference) ui.findPreference(UserPreferences.PREF_SONIC);
- if(prefSonic != null) {
- prefSonic.setChecked(sharedPreferences.getBoolean(UserPreferences.PREF_SONIC, false));
- }
- }
- }
-
/**
* Returns the preference activity that should be used on this device.
*
* @return PreferenceActivity if the API level is greater than 10, PreferenceActivityGingerbread otherwise.
*/
- public static Class getPreferenceActivity() {
+ public static Class<? extends Activity> getPreferenceActivity() {
if (Build.VERSION.SDK_INT > 10) {
return PreferenceActivity.class;
} else {
@@ -135,6 +145,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
}
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if(key.equals(UserPreferences.PREF_SONIC)) {
+ CheckBoxPreference prefSonic = (CheckBoxPreference) ui.findPreference(UserPreferences.PREF_SONIC);
+ if(prefSonic != null) {
+ prefSonic.setChecked(sharedPreferences.getBoolean(UserPreferences.PREF_SONIC, false));
+ }
+ }
+ }
+
public void onCreate() {
final Activity activity = ui.getActivity();
@@ -170,11 +190,9 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
);
ui.findPreference(PreferenceController.PREF_OPML_EXPORT).setOnPreferenceClickListener(
- preference -> {
- new OpmlExportWorker(activity).executeAsync();
- return true;
- }
- );
+ preference -> export(new OpmlWriter()));
+ ui.findPreference(PreferenceController.PREF_HTML_EXPORT).setOnPreferenceClickListener(
+ preference -> export(new HtmlWriter()));
ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener(
preference -> {
if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT &&
@@ -318,6 +336,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
VariableSpeedDialog.showDialog(activity);
return true;
});
+ ui.findPreference(PreferenceController.PREF_PLAYBACK_REWIND_DELTA_LAUNCHER)
+ .setOnPreferenceClickListener(preference -> {
+ MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_REWIND);
+ return true;
+ });
+ ui.findPreference(PreferenceController.PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER)
+ .setOnPreferenceClickListener(preference -> {
+ MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_FORWARD);
+ return true;
+ });
ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION)
.setOnPreferenceClickListener(preference -> {
AuthenticationDialog dialog = new AuthenticationDialog(activity,
@@ -340,6 +368,18 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
toast.show();
return true;
});
+ ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC).
+ setOnPreferenceClickListener(preference -> {
+ GpodnetPreferences.setLastSubscriptionSyncTimestamp(0L);
+ GpodnetPreferences.setLastEpisodeActionsSyncTimestamp(0L);
+ GpodnetPreferences.setLastSyncAttempt(false, 0);
+ updateLastGpodnetSyncReport(false, 0);
+ GpodnetSyncService.sendSyncIntent(ui.getActivity().getApplicationContext());
+ Toast toast = Toast.makeText(ui.getActivity(), R.string.pref_gpodnet_sync_started,
+ Toast.LENGTH_SHORT);
+ toast.show();
+ return true;
+ });
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setOnPreferenceClickListener(
preference -> {
GpodnetPreferences.logout();
@@ -412,28 +452,47 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
ui.getActivity().startActivity(Intent.createChooser(emailIntent, intentTitle));
return true;
});
- //checks whether Google Play Services is installed on the device (condition necessary for Cast support)
- ui.findPreference(UserPreferences.PREF_CAST_ENABLED).setOnPreferenceChangeListener((preference, o) -> {
- if (o instanceof Boolean && ((Boolean) o)) {
- final int googlePlayServicesCheck = GoogleApiAvailability.getInstance()
- .isGooglePlayServicesAvailable(ui.getActivity());
- if (googlePlayServicesCheck == ConnectionResult.SUCCESS) {
- return true;
- } else {
- GoogleApiAvailability.getInstance()
- .getErrorDialog(ui.getActivity(), googlePlayServicesCheck, 0)
- .show();
- return false;
- }
- }
- return true;
- });
+ PreferenceControllerFlavorHelper.setupFlavoredUI(ui);
buildEpisodeCleanupPreference();
buildSmartMarkAsPlayedPreference();
buildAutodownloadSelectedNetworsPreference();
setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter());
}
+ private boolean export(ExportWriter exportWriter) {
+ Context context = ui.getActivity();
+ final ProgressDialog progressDialog = new ProgressDialog(context);
+ progressDialog.setMessage(context.getString(R.string.exporting_label));
+ progressDialog.setIndeterminate(true);
+ progressDialog.show();
+ final AlertDialog.Builder alert = new AlertDialog.Builder(context)
+ .setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss());
+ Observable<File> observable = new ExportWorker(exportWriter).exportObservable();
+ subscription = observable.subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(output -> {
+ alert.setTitle(R.string.opml_export_success_title);
+ String message = context.getString(R.string.opml_export_success_sum) + output.toString();
+ alert.setMessage(message);
+ alert.setPositiveButton(R.string.send_label, (dialog, which) -> {
+ Uri outputUri = Uri.fromFile(output);
+ Intent sendIntent = new Intent(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_SUBJECT,
+ context.getResources().getText(R.string.opml_export_label));
+ sendIntent.putExtra(Intent.EXTRA_STREAM, outputUri);
+ sendIntent.setType("text/plain");
+ context.startActivity(Intent.createChooser(sendIntent,
+ context.getResources().getText(R.string.send_label)));
+ });
+ alert.create().show();
+ }, error -> {
+ alert.setTitle(R.string.export_error_label);
+ alert.setMessage(error.getMessage());
+ alert.show();
+ }, () -> progressDialog.dismiss());
+ return true;
+ }
+
private void openInBrowser(String url) {
try {
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
@@ -450,9 +509,20 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
setParallelDownloadsText(UserPreferences.getParallelDownloads());
setEpisodeCacheSizeText(UserPreferences.getEpisodeCacheSize());
setDataFolderText();
+ GpodnetPreferences.registerOnSharedPreferenceChangeListener(gpoddernetListener);
updateGpodnetPreferenceScreen();
}
+ public void onPause() {
+ GpodnetPreferences.unregisterOnSharedPreferenceChangeListener(gpoddernetListener);
+ }
+
+ public void onStop() {
+ if(subscription != null) {
+ subscription.unsubscribe();
+ }
+ }
+
@SuppressLint("NewApi")
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK &&
@@ -494,18 +564,41 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
ui.findPreference(PreferenceController.PREF_GPODNET_LOGIN).setEnabled(!loggedIn);
ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION).setEnabled(loggedIn);
ui.findPreference(PreferenceController.PREF_GPODNET_SYNC).setEnabled(loggedIn);
+ ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC).setEnabled(loggedIn);
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setEnabled(loggedIn);
+ ui.findPreference(PREF_GPODNET_NOTIFICATIONS).setEnabled(loggedIn);
if(loggedIn) {
String format = ui.getActivity().getString(R.string.pref_gpodnet_login_status);
String summary = String.format(format, GpodnetPreferences.getUsername(),
GpodnetPreferences.getDeviceID());
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setSummary(Html.fromHtml(summary));
+ updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(),
+ GpodnetPreferences.getLastSyncAttemptTimestamp());
} else {
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setSummary(null);
+ updateLastGpodnetSyncReport(false, 0);
}
ui.findPreference(PreferenceController.PREF_GPODNET_HOSTNAME).setSummary(GpodnetPreferences.getHostname());
}
+ private void updateLastGpodnetSyncReport(boolean successful, long lastTime) {
+ Preference sync = ui.findPreference(PREF_GPODNET_SYNC);
+ if (lastTime != 0) {
+ sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum) + "\n" +
+ ui.getActivity().getString(R.string.pref_gpodnet_sync_sum_last_sync_line,
+ ui.getActivity().getString(successful ?
+ R.string.gpodnetsync_pref_report_successful :
+ R.string.gpodnetsync_pref_report_failed),
+ DateUtils.getRelativeDateTimeString(ui.getActivity(),
+ lastTime,
+ DateUtils.MINUTE_IN_MILLIS,
+ DateUtils.WEEK_IN_MILLIS,
+ DateUtils.FORMAT_SHOW_TIME)));
+ } else {
+ sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum));
+ }
+ }
+
private String[] getUpdateIntervalEntries(final String[] values) {
final Resources res = ui.getActivity().getResources();
String[] entries = new String[values.length];
@@ -621,7 +714,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
val = String.format(context.getString(R.string.pref_autoUpdateIntervallOrTime_at),
timeOfDayStr);
} else {
- val = context.getString(R.string.pref_smart_mark_as_played_disabled);
+ val = context.getString(R.string.pref_smart_mark_as_played_disabled); // TODO: Is this a bug? Otherwise document why is this related to smart mark???
}
}
String summary = context.getString(R.string.pref_autoUpdateIntervallOrTime_sum) + "\n"
@@ -666,10 +759,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
clearAutodownloadSelectedNetworsPreference();
}
// get configured networks
- WifiManager wifiservice = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
+ WifiManager wifiservice = (WifiManager) activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
List<WifiConfiguration> networks = wifiservice.getConfiguredNetworks();
if (networks != null) {
+ Collections.sort(networks, new Comparator<WifiConfiguration>() {
+ @Override
+ public int compare(WifiConfiguration x, WifiConfiguration y) {
+ return x.SSID.compareTo(y.SSID);
+ }
+ });
selectedNetworks = new CheckBoxPreference[networks.size()];
List<String> prefValues = Arrays.asList(UserPreferences
.getAutodownloadSelectedNetworks());
@@ -754,9 +853,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]);
}
});
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- UserPreferences.setHiddenDrawerItems(hiddenDrawerItems);
- });
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) ->
+ UserPreferences.setHiddenDrawerItems(hiddenDrawerItems));
builder.setNegativeButton(R.string.cancel_label, null);
builder.create().show();
}
@@ -800,9 +898,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
preferredButtons.remove((Integer) which);
}
});
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- UserPreferences.setCompactNotificationButtons(preferredButtons);
- });
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) ->
+ UserPreferences.setCompactNotificationButtons(preferredButtons));
builder.setNegativeButton(R.string.cancel_label, null);
builder.create().show();
}