summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/build.gradle2
-rw-r--r--app/src/main/AndroidManifest.xml4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java49
-rw-r--r--app/src/main/java/de/danoeh/antennapod/PodcastApp.java19
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java572
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java14
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java14
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java45
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java21
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java25
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java136
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java78
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java15
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java61
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java79
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java16
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java89
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java110
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java58
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java153
-rw-r--r--app/src/main/res/layout/downloadlog_item.xml3
-rw-r--r--app/src/main/res/layout/feeditemlist_item.xml9
-rw-r--r--app/src/main/res/layout/new_episodes_listitem.xml14
-rw-r--r--app/src/main/res/layout/queue_listitem.xml13
-rw-r--r--app/src/main/res/xml/preferences.xml10
33 files changed, 984 insertions, 657 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 3368af0d6..0e6c9865b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -19,6 +19,7 @@ dependencies {
compile("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") {
exclude group: "org.json", module: "json"
}
+
compile "commons-io:commons-io:$commonsioVersion"
compile "org.jsoup:jsoup:$jsoupVersion"
compile "com.github.bumptech.glide:glide:$glideVersion"
@@ -27,6 +28,7 @@ dependencies {
compile "com.squareup.okio:okio:$okioVersion"
compile "de.greenrobot:eventbus:$eventbusVersion"
compile "io.reactivex:rxandroid:$rxAndroidVersion"
+ compile "io.reactivex:rxjava:$rxJavaVersion"
compile "com.joanzapata.iconify:android-iconify-fontawesome:2.1.0"
compile "com.afollestad:material-dialogs:0.7.8.1"
compile "com.yqritc:recyclerview-flexibledivider:1.2.6"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 636e1e64c..4efd5f5b6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.danoeh.antennapod"
- android:versionCode="1040008"
- android:versionName="1.4.0.8">
+ android:versionCode="1040012"
+ android:versionName="1.4.0.12">
<!--
Version code schema:
"1.2.3-SNAPSHOT" -> 1020300
diff --git a/app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java b/app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java
new file mode 100644
index 000000000..17942a93c
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java
@@ -0,0 +1,49 @@
+package de.danoeh.antennapod;
+
+import android.os.Build;
+import android.util.Log;
+
+import org.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+
+public class CrashReportWriter implements Thread.UncaughtExceptionHandler {
+
+ private static final String TAG = "CrashReportWriter";
+
+ private final Thread.UncaughtExceptionHandler defaultHandler;
+
+ public CrashReportWriter() {
+ defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
+ }
+
+ public static File getFile() {
+ return new File(UserPreferences.getDataFolder(null), "crash-report.log");
+ }
+
+ @Override
+ public void uncaughtException(Thread thread, Throwable ex) {
+ File path = getFile();
+ PrintWriter out = null;
+ try {
+ out = new PrintWriter(new FileWriter(path));
+ out.println("[ Environment ]");
+ out.println("Android version: " + Build.VERSION.RELEASE);
+ out.println("AntennaPod version: " + BuildConfig.VERSION_NAME);
+ out.println("Phone model: " + Build.MODEL);
+ out.println();
+ out.println("[ StackTrace ]");
+ ex.printStackTrace(out);
+ } catch (IOException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ } finally {
+ IOUtils.closeQuietly(out);
+ }
+ defaultHandler.uncaughtException(thread, ex);
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
index 83bc9afb2..835f43f40 100644
--- a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
+++ b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
@@ -1,7 +1,6 @@
package de.danoeh.antennapod;
import android.app.Application;
-import android.content.res.Configuration;
import android.os.Build;
import android.os.StrictMode;
@@ -27,10 +26,6 @@ public class PodcastApp extends Application {
}
}
- private static final String TAG = "PodcastApp";
-
- private static float LOGICAL_DENSITY;
-
private static PodcastApp singleton;
public static PodcastApp getInstance() {
@@ -41,6 +36,8 @@ public class PodcastApp extends Application {
public void onCreate() {
super.onCreate();
+ Thread.setDefaultUncaughtExceptionHandler(new CrashReportWriter());
+
if(BuildConfig.DEBUG) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
@@ -57,7 +54,6 @@ public class PodcastApp extends Application {
}
singleton = this;
- LOGICAL_DENSITY = getResources().getDisplayMetrics().density;
PodDBAdapter.init(this);
UpdateManager.init(this);
@@ -68,15 +64,6 @@ public class PodcastApp extends Application {
Iconify.with(new FontAwesomeModule());
SPAUtil.sendSPAppsQueryFeedsIntent(this);
- }
-
- public static float getLogicalDensity() {
- return LOGICAL_DENSITY;
- }
-
- public boolean isLargeScreen() {
- return (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE
- || (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE;
+ }
- }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
index b87870c69..4a43dc3c6 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
@@ -772,7 +772,7 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
private DBReader.NavDrawerData navDrawerData;
private void loadData() {
- subscription = Observable.defer(() -> Observable.just(DBReader.getNavDrawerData()))
+ subscription = Observable.fromCallable(() -> DBReader.getNavDrawerData())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
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 86ca90eb5..25dc64232 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java
@@ -1,7 +1,6 @@
package de.danoeh.antennapod.activity;
import android.app.Activity;
-import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
@@ -15,93 +14,98 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
-import android.widget.*;
-import android.widget.AdapterView.OnItemClickListener;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import de.danoeh.antennapod.BuildConfig;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+
/**
* Let's the user choose a directory on the storage device. The selected folder
* will be sent back to the starting activity as an activity result.
*/
public class DirectoryChooserActivity extends ActionBarActivity {
- private static final String TAG = "DirectoryChooserActivity";
-
- private static final String CREATE_DIRECTORY_NAME = "AntennaPod";
-
- public static final String RESULT_SELECTED_DIR = "selected_dir";
- public static final int RESULT_CODE_DIR_SELECTED = 1;
-
- private Button butConfirm;
- private Button butCancel;
- private ImageButton butNavUp;
- private TextView txtvSelectedFolder;
- private ListView listDirectories;
-
- private ArrayAdapter<String> listDirectoriesAdapter;
- private ArrayList<String> filenames;
- /** The directory that is currently being shown. */
- private File selectedDir;
- private File[] filesInDir;
-
- private FileObserver fileObserver;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- setContentView(R.layout.directory_chooser);
- butConfirm = (Button) findViewById(R.id.butConfirm);
- butCancel = (Button) findViewById(R.id.butCancel);
- butNavUp = (ImageButton) findViewById(R.id.butNavUp);
- txtvSelectedFolder = (TextView) findViewById(R.id.txtvSelectedFolder);
- listDirectories = (ListView) findViewById(R.id.directory_list);
-
- butConfirm.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (isValidFile(selectedDir)) {
- if (selectedDir.list().length == 0) {
- returnSelectedFolder();
- } else {
- showNonEmptyDirectoryWarning();
- }
- }
- }
-
- private void showNonEmptyDirectoryWarning() {
- AlertDialog.Builder adb = new AlertDialog.Builder(
- DirectoryChooserActivity.this);
- 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) -> {
+ private static final String TAG = "DirectoryChooserActivit";
+
+ private static final String CREATE_DIRECTORY_NAME = "AntennaPod";
+
+ public static final String RESULT_SELECTED_DIR = "selected_dir";
+ public static final int RESULT_CODE_DIR_SELECTED = 1;
+
+ private Button butConfirm;
+ private Button butCancel;
+ private ImageButton butNavUp;
+ private TextView txtvSelectedFolder;
+ private ListView listDirectories;
+
+ private ArrayAdapter<String> listDirectoriesAdapter;
+ private ArrayList<String> filenames;
+ /** The directory that is currently being shown. */
+ private File selectedDir;
+ private File[] filesInDir;
+
+ private FileObserver fileObserver;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ setTheme(UserPreferences.getTheme());
+ super.onCreate(savedInstanceState);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ setContentView(R.layout.directory_chooser);
+ butConfirm = (Button) findViewById(R.id.butConfirm);
+ butCancel = (Button) findViewById(R.id.butCancel);
+ butNavUp = (ImageButton) findViewById(R.id.butNavUp);
+ txtvSelectedFolder = (TextView) findViewById(R.id.txtvSelectedFolder);
+ listDirectories = (ListView) findViewById(R.id.directory_list);
+
+ butConfirm.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (isValidFile(selectedDir)) {
+ if (selectedDir.list().length == 0) {
+ returnSelectedFolder();
+ } else {
+ showNonEmptyDirectoryWarning();
+ }
+ }
+ }
+
+ private void showNonEmptyDirectoryWarning() {
+ AlertDialog.Builder adb = new AlertDialog.Builder(
+ DirectoryChooserActivity.this);
+ 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();
});
- adb.setPositiveButton(R.string.confirm_label,
- (dialog, which) -> {
+ adb.setPositiveButton(R.string.confirm_label,
+ (dialog, which) -> {
dialog.dismiss();
returnSelectedFolder();
});
- adb.create().show();
- }
- });
+ adb.create().show();
+ }
+ });
- butCancel.setOnClickListener(v -> {
+ butCancel.setOnClickListener(v -> {
setResult(Activity.RESULT_CANCELED);
finish();
});
- listDirectories.setOnItemClickListener((adapter, view, position, id) -> {
+ listDirectories.setOnItemClickListener((adapter, view, position, id) -> {
Log.d(TAG, "Selected index: " + position);
if (filesInDir != null && position >= 0
&& position < filesInDir.length) {
@@ -109,7 +113,7 @@ public class DirectoryChooserActivity extends ActionBarActivity {
}
});
- butNavUp.setOnClickListener(v -> {
+ butNavUp.setOnClickListener(v -> {
File parent = null;
if (selectedDir != null
&& (parent = selectedDir.getParentFile()) != null) {
@@ -117,230 +121,216 @@ public class DirectoryChooserActivity extends ActionBarActivity {
}
});
- filenames = new ArrayList<>();
- listDirectoriesAdapter = new ArrayAdapter<>(this,
- android.R.layout.simple_list_item_1, filenames);
- listDirectories.setAdapter(listDirectoriesAdapter);
- changeDirectory(Environment.getExternalStorageDirectory());
- }
-
- /**
- * Finishes the activity and returns the selected folder as a result. The
- * selected folder can also be null.
- */
- private void returnSelectedFolder() {
- if (selectedDir != null && BuildConfig.DEBUG)
- Log.d(TAG, "Returning " + selectedDir.getAbsolutePath()
- + " as result");
- Intent resultData = new Intent();
- if (selectedDir != null) {
- resultData.putExtra(RESULT_SELECTED_DIR,
- selectedDir.getAbsolutePath());
- }
- setResult(RESULT_CODE_DIR_SELECTED, resultData);
- finish();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- if (fileObserver != null) {
- fileObserver.stopWatching();
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (fileObserver != null) {
- fileObserver.startWatching();
- }
- }
-
- /**
- * Change the directory that is currently being displayed.
- *
- * @param dir
- * The file the activity should switch to. This File must be
- * non-null and a directory, otherwise the displayed directory
- * will not be changed
- */
- private void changeDirectory(File dir) {
- if (dir != null && dir.isDirectory()) {
- File[] contents = dir.listFiles();
- if (contents != null) {
- int numDirectories = 0;
- for (File f : contents) {
- if (f.isDirectory()) {
- numDirectories++;
- }
- }
- filesInDir = new File[numDirectories];
- filenames.clear();
- for (int i = 0, counter = 0; i < numDirectories; counter++) {
- if (contents[counter].isDirectory()) {
- filesInDir[i] = contents[counter];
- filenames.add(contents[counter].getName());
- i++;
- }
- }
- Arrays.sort(filesInDir);
- Collections.sort(filenames);
- selectedDir = dir;
- txtvSelectedFolder.setText(dir.getAbsolutePath());
- listDirectoriesAdapter.notifyDataSetChanged();
- fileObserver = createFileObserver(dir.getAbsolutePath());
- fileObserver.startWatching();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Changed directory to " + dir.getAbsolutePath());
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Could not change folder: contents of dir were null");
- }
- } else {
- if (dir == null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Could not change folder: dir was null");
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Could not change folder: dir is no directory");
- }
- }
- refreshButtonState();
- }
-
- /**
- * Changes the state of the buttons depending on the currently selected file
- * or folder.
- */
- private void refreshButtonState() {
- if (selectedDir != null) {
- butConfirm.setEnabled(isValidFile(selectedDir));
- supportInvalidateOptionsMenu();
- }
- }
-
- /** Refresh the contents of the directory that is currently shown. */
- private void refreshDirectory() {
- if (selectedDir != null) {
- changeDirectory(selectedDir);
- }
- }
-
- /** Sets up a FileObserver to watch the current directory. */
- private FileObserver createFileObserver(String path) {
- return new FileObserver(path, FileObserver.CREATE | FileObserver.DELETE
- | FileObserver.MOVED_FROM | FileObserver.MOVED_TO) {
-
- @Override
- public void onEvent(int event, String path) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "FileObserver received event " + event);
- runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- refreshDirectory();
- }
- });
- }
- };
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
+ filenames = new ArrayList<>();
+ listDirectoriesAdapter = new ArrayAdapter<>(this,
+ android.R.layout.simple_list_item_1, filenames);
+ listDirectories.setAdapter(listDirectoriesAdapter);
+ changeDirectory(Environment.getExternalStorageDirectory());
+ }
+
+ /**
+ * Finishes the activity and returns the selected folder as a result. The
+ * selected folder can also be null.
+ */
+ private void returnSelectedFolder() {
+ if (selectedDir != null && BuildConfig.DEBUG)
+ Log.d(TAG, "Returning " + selectedDir.getAbsolutePath()
+ + " as result");
+ Intent resultData = new Intent();
+ if (selectedDir != null) {
+ resultData.putExtra(RESULT_SELECTED_DIR,
+ selectedDir.getAbsolutePath());
+ }
+ setResult(Activity.RESULT_OK, resultData);
+ finish();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (fileObserver != null) {
+ fileObserver.stopWatching();
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (fileObserver != null) {
+ fileObserver.startWatching();
+ }
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ listDirectoriesAdapter = null;
+ fileObserver = null;
+ }
+
+ /**
+ * Change the directory that is currently being displayed.
+ *
+ * @param dir
+ * The file the activity should switch to. This File must be
+ * non-null and a directory, otherwise the displayed directory
+ * will not be changed
+ */
+ private void changeDirectory(File dir) {
+ if (dir != null && dir.isDirectory()) {
+ File[] contents = dir.listFiles();
+ if (contents != null) {
+ int numDirectories = 0;
+ for (File f : contents) {
+ if (f.isDirectory()) {
+ numDirectories++;
+ }
+ }
+ filesInDir = new File[numDirectories];
+ filenames.clear();
+ for (int i = 0, counter = 0; i < numDirectories; counter++) {
+ if (contents[counter].isDirectory()) {
+ filesInDir[i] = contents[counter];
+ filenames.add(contents[counter].getName());
+ i++;
+ }
+ }
+ Arrays.sort(filesInDir);
+ Collections.sort(filenames);
+ selectedDir = dir;
+ txtvSelectedFolder.setText(dir.getAbsolutePath());
+ listDirectoriesAdapter.notifyDataSetChanged();
+ fileObserver = createFileObserver(dir.getAbsolutePath());
+ fileObserver.startWatching();
+ Log.d(TAG, "Changed directory to " + dir.getAbsolutePath());
+ } else {
+ Log.d(TAG, "Could not change folder: contents of dir were null");
+ }
+ } else {
+ if (dir == null) {
+ Log.d(TAG, "Could not change folder: dir was null");
+ } else {
+ Log.d(TAG, "Could not change folder: dir is no directory");
+ }
+ }
+ refreshButtonState();
+ }
+
+ /**
+ * Changes the state of the buttons depending on the currently selected file
+ * or folder.
+ */
+ private void refreshButtonState() {
+ if (selectedDir != null) {
+ butConfirm.setEnabled(isValidFile(selectedDir));
+ supportInvalidateOptionsMenu();
+ }
+ }
+
+ /** Refresh the contents of the directory that is currently shown. */
+ private void refreshDirectory() {
+ if (selectedDir != null) {
+ changeDirectory(selectedDir);
+ }
+ }
+
+ /** Sets up a FileObserver to watch the current directory. */
+ private FileObserver createFileObserver(String path) {
+ return new FileObserver(path, FileObserver.CREATE | FileObserver.DELETE
+ | FileObserver.MOVED_FROM | FileObserver.MOVED_TO) {
+
+ @Override
+ public void onEvent(int event, String path) {
+ Log.d(TAG, "FileObserver received event " + event);
+ runOnUiThread(() -> refreshDirectory());
+ }
+ };
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- menu.findItem(R.id.new_folder_item)
- .setVisible(isValidFile(selectedDir));
- return true;
- }
+ menu.findItem(R.id.new_folder_item)
+ .setVisible(isValidFile(selectedDir));
+ return true;
+ }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.directory_chooser, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- NavUtils.navigateUpFromSameTask(this);
- return true;
- case R.id.new_folder_item:
- openNewFolderDialog();
- return true;
- case R.id.set_to_default_folder_item:
- selectedDir = null;
- returnSelectedFolder();
- return true;
- default:
- return false;
- }
- }
-
- /**
- * Shows a confirmation dialog that asks the user if he wants to create a
- * new folder.
- */
- private void openNewFolderDialog() {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.create_folder_label);
- builder.setMessage(String.format(getString(R.string.create_folder_msg),
- CREATE_DIRECTORY_NAME));
- builder.setNegativeButton(R.string.cancel_label,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- });
- builder.setPositiveButton(R.string.confirm_label,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- int msg = createFolder();
- Toast t = Toast.makeText(DirectoryChooserActivity.this,
- msg, Toast.LENGTH_SHORT);
- t.show();
- }
- });
- builder.create().show();
- }
-
- /**
- * Creates a new folder in the current directory with the name
- * CREATE_DIRECTORY_NAME.
- */
- private int createFolder() {
- if (selectedDir == null) {
- return R.string.create_folder_error;
- } else if (selectedDir.canWrite()) {
- File newDir = new File(selectedDir, CREATE_DIRECTORY_NAME);
- if (!newDir.exists()) {
- boolean result = newDir.mkdir();
- if (result) {
- return R.string.create_folder_success;
- } else {
- return R.string.create_folder_error;
- }
- } else {
- return R.string.create_folder_error_already_exists;
- }
- } else {
- return R.string.create_folder_error_no_write_access;
- }
- }
-
- /** Returns true if the selected file or directory would be valid selection. */
- private boolean isValidFile(File file) {
- return (file != null && file.isDirectory() && file.canRead() && file
- .canWrite());
- }
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.directory_chooser, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ NavUtils.navigateUpFromSameTask(this);
+ return true;
+ case R.id.new_folder_item:
+ openNewFolderDialog();
+ return true;
+ case R.id.set_to_default_folder_item:
+ selectedDir = null;
+ returnSelectedFolder();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Shows a confirmation dialog that asks the user if he wants to create a
+ * new folder.
+ */
+ private void openNewFolderDialog() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.create_folder_label);
+ builder.setMessage(String.format(getString(R.string.create_folder_msg),
+ CREATE_DIRECTORY_NAME));
+ builder.setNegativeButton(R.string.cancel_label,
+ (dialog, which) -> {
+ dialog.dismiss();
+ });
+ builder.setPositiveButton(R.string.confirm_label,
+ (dialog, which) -> {
+ dialog.dismiss();
+ int msg = createFolder();
+ Toast t = Toast.makeText(DirectoryChooserActivity.this,
+ msg, Toast.LENGTH_SHORT);
+ t.show();
+ });
+ builder.create().show();
+ }
+
+ /**
+ * Creates a new folder in the current directory with the name
+ * CREATE_DIRECTORY_NAME.
+ */
+ private int createFolder() {
+ if (selectedDir == null) {
+ return R.string.create_folder_error;
+ } else if (selectedDir.canWrite()) {
+ File newDir = new File(selectedDir, CREATE_DIRECTORY_NAME);
+ if (!newDir.exists()) {
+ boolean result = newDir.mkdir();
+ if (result) {
+ return R.string.create_folder_success;
+ } else {
+ return R.string.create_folder_error;
+ }
+ } else {
+ return R.string.create_folder_error_already_exists;
+ }
+ } else {
+ return R.string.create_folder_error_no_write_access;
+ }
+ }
+
+ /** Returns true if the selected file or directory would be valid selection. */
+ private boolean isValidFile(File file) {
+ return file != null && file.isDirectory() && file.canRead() && file.canWrite();
+ }
}
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 6915c817b..211b895d0 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
@@ -8,6 +8,7 @@ import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.database.DataSetObserver;
import android.media.AudioManager;
+import android.media.Rating;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
@@ -41,10 +42,9 @@ 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.ProgressEvent;
+import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.event.QueueEvent;
-import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
@@ -54,6 +54,7 @@ import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
+import de.danoeh.antennapod.dialog.RatingDialog;
import de.danoeh.antennapod.fragment.AddFeedFragment;
import de.danoeh.antennapod.fragment.DownloadsFragment;
import de.danoeh.antennapod.fragment.EpisodesFragment;
@@ -76,9 +77,7 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
private static final String TAG = "MainActivity";
- private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED
- | EventDistributor.DOWNLOAD_QUEUED
- | EventDistributor.FEED_LIST_UPDATE
+ private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE
| EventDistributor.UNREAD_ITEMS_UPDATE;
public static final String PREF_NAME = "MainActivityPrefs";
@@ -452,6 +451,7 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
super.onStart();
EventDistributor.getInstance().register(contentUpdate);
EventBus.getDefault().register(this);
+ RatingDialog.init(this);
}
@Override
@@ -469,8 +469,8 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
(intent.hasExtra(EXTRA_NAV_INDEX) || intent.hasExtra(EXTRA_FRAGMENT_TAG))) {
handleNavIntent();
}
-
loadData();
+ RatingDialog.check();
}
@Override
@@ -639,7 +639,7 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
};
private void loadData() {
- subscription = Observable.defer(() -> Observable.just(DBReader.getNavDrawerData()))
+ subscription = Observable.fromCallable(() -> DBReader.getNavDrawerData())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
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 c67d65a9d..b32389bd9 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
@@ -41,6 +41,7 @@ import java.util.Map;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.FeedItemlistDescriptionAdapter;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
+import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -63,6 +64,7 @@ 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.dialog.AuthenticationDialog;
+import de.greenrobot.event.EventBus;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
@@ -86,7 +88,7 @@ public class OnlineFeedViewActivity extends ActionBarActivity {
// Optional argument: specify a title for the actionbar.
public static final String ARG_TITLE = "title";
- private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED | EventDistributor.DOWNLOAD_QUEUED | EventDistributor.FEED_LIST_UPDATE;
+ private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE;
public static final int RESULT_ERROR = 2;
@@ -105,11 +107,16 @@ public class OnlineFeedViewActivity extends ActionBarActivity {
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.defer(() -> Observable.just(DBReader.getFeedList()))
+ updater = Observable.fromCallable(() -> DBReader.getFeedList())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(feeds -> {
@@ -180,7 +187,7 @@ public class OnlineFeedViewActivity extends ActionBarActivity {
super.onResume();
isPaused = false;
EventDistributor.getInstance().register(listener);
-
+ EventBus.getDefault().register(this);
}
@Override
@@ -188,6 +195,7 @@ public class OnlineFeedViewActivity extends ActionBarActivity {
super.onPause();
isPaused = true;
EventDistributor.getInstance().unregister(listener);
+ EventBus.getDefault().unregister(this);
}
@Override
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 74cf6af60..1a8f0a67a 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java
@@ -7,14 +7,10 @@ import android.widget.ImageButton;
import org.apache.commons.lang3.Validate;
-import java.lang.ref.WeakReference;
-
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
-import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DownloadRequester;
-import de.danoeh.antennapod.core.util.LongList;
/**
* Utility methods for the action button that is displayed on the right hand side
@@ -51,7 +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.
*/
- public void configureActionButton(ImageButton butSecondary, FeedItem item) {
+ public void configureActionButton(ImageButton butSecondary, FeedItem item, boolean isInQueue) {
Validate.isTrue(butSecondary != null && item != null, "butSecondary or item was null");
final FeedMedia media = item.getMedia();
@@ -66,9 +62,8 @@ public class ActionButtonUtils {
butSecondary.setContentDescription(context.getString(labels[1]));
} else {
// item is not downloaded and not being downloaded
- LongList queueIds = DBReader.getQueueIDList();
if(DefaultActionButtonCallback.userAllowedMobileDownloads() ||
- !DefaultActionButtonCallback.userChoseAddToQueue() || queueIds.contains(item.getId())) {
+ !DefaultActionButtonCallback.userChoseAddToQueue() || isInQueue) {
butSecondary.setVisibility(View.VISIBLE);
butSecondary.setImageDrawable(drawables.getDrawable(2));
butSecondary.setContentDescription(context.getString(labels[2]));
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 b35ff0aa9..f120aa1d5 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
@@ -1,22 +1,21 @@
package de.danoeh.antennapod.adapter;
-import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.ContextMenu;
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.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -34,7 +33,7 @@ import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
-import de.danoeh.antennapod.core.storage.DownloadRequestException;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.NetworkUtils;
@@ -48,27 +47,34 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
private static final String TAG = AllEpisodesRecycleAdapter.class.getSimpleName();
- private final Context context;
+ private final WeakReference<MainActivity> mainActivityRef;
private final ItemAccess itemAccess;
private final ActionButtonCallback actionButtonCallback;
private final ActionButtonUtils actionButtonUtils;
private final boolean showOnlyNewEpisodes;
- private final WeakReference<MainActivity> mainActivityRef;
private int position = -1;
- public AllEpisodesRecycleAdapter(Context context,
- MainActivity mainActivity,
+ private final int playingBackGroundColor;
+ private final int normalBackGroundColor;
+
+ public AllEpisodesRecycleAdapter(MainActivity mainActivity,
ItemAccess itemAccess,
ActionButtonCallback actionButtonCallback,
boolean showOnlyNewEpisodes) {
super();
this.mainActivityRef = new WeakReference<>(mainActivity);
- this.context = context;
this.itemAccess = itemAccess;
- this.actionButtonUtils = new ActionButtonUtils(context);
+ this.actionButtonUtils = new ActionButtonUtils(mainActivity);
this.actionButtonCallback = actionButtonCallback;
this.showOnlyNewEpisodes = showOnlyNewEpisodes;
+
+ if(UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
+ playingBackGroundColor = mainActivity.getResources().getColor(R.color.highlight_dark);
+ } else {
+ playingBackGroundColor = mainActivity.getResources().getColor(R.color.highlight_light);
+ }
+ normalBackGroundColor = mainActivity.getResources().getColor(android.R.color.transparent);
}
@Override
@@ -76,6 +82,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.new_episodes_listitem, parent, false);
Holder holder = new Holder(view);
+ holder.container = (FrameLayout) view.findViewById(R.id.container);
holder.placeholder = (TextView) view.findViewById(R.id.txtvPlaceholder);
holder.title = (TextView) view.findViewById(R.id.txtvTitle);
holder.pubDate = (TextView) view
@@ -111,7 +118,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.placeholder.setVisibility(View.VISIBLE);
holder.placeholder.setText(item.getFeed().getTitle());
holder.title.setText(item.getTitle());
- holder.pubDate.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL));
+ holder.pubDate.setText(DateUtils.formatDateTime(mainActivityRef.get(),
+ item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL));
if (showOnlyNewEpisodes || false == item.isNew()) {
holder.statusUnread.setVisibility(View.INVISIBLE);
} else {
@@ -161,23 +169,29 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.progress.setVisibility(View.GONE);
}
+ if(media.isCurrentlyPlaying()) {
+ holder.container.setBackgroundColor(playingBackGroundColor);
+ } else {
+ holder.container.setBackgroundColor(normalBackGroundColor);
+ }
} else {
holder.progress.setVisibility(View.GONE);
holder.txtvDuration.setVisibility(View.GONE);
}
- if (itemAccess.isInQueue(item)) {
+ boolean isInQueue = itemAccess.isInQueue(item);
+ if (isInQueue) {
holder.queueStatus.setVisibility(View.VISIBLE);
} else {
holder.queueStatus.setVisibility(View.INVISIBLE);
}
- actionButtonUtils.configureActionButton(holder.butSecondary, item);
+ actionButtonUtils.configureActionButton(holder.butSecondary, item, isInQueue);
holder.butSecondary.setFocusable(false);
holder.butSecondary.setTag(item);
holder.butSecondary.setOnClickListener(secondaryActionListener);
- Glide.with(context)
+ Glide.with(mainActivityRef.get())
.load(item.getImageUri())
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
@@ -224,7 +238,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
TextView txtvPlaceholder = placeholder.get();
ImageView imgvCover = cover.get();
if(fallbackUri != null && txtvPlaceholder != null && imgvCover != null) {
- Glide.with(context)
+ Glide.with(mainActivityRef.get())
.load(fallbackUri)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
@@ -255,6 +269,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
implements View.OnClickListener,
View.OnCreateContextMenuListener,
ItemTouchHelperViewHolder {
+ FrameLayout container;
TextView placeholder;
TextView title;
TextView pubDate;
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
index 4ccff39af..9d7a509cf 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
@@ -7,11 +7,11 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
-import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.joanzapata.iconify.Iconify;
+import com.joanzapata.iconify.widget.IconButton;
import java.util.Date;
@@ -50,7 +50,7 @@ public class DownloadLogAdapter extends BaseAdapter {
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.downloadlog_item, parent, false);
holder.icon = (TextView) convertView.findViewById(R.id.txtvIcon);
- holder.retry = (Button) convertView.findViewById(R.id.btnRetry);
+ holder.retry = (IconButton) convertView.findViewById(R.id.btnRetry);
holder.date = (TextView) convertView.findViewById(R.id.txtvDate);
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
holder.type = (TextView) convertView.findViewById(R.id.txtvType);
@@ -96,8 +96,6 @@ public class DownloadLogAdapter extends BaseAdapter {
if(status.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE &&
!newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) {
holder.retry.setVisibility(View.VISIBLE);
- holder.retry.setText("{fa-repeat}");
- Iconify.addIcons(holder.retry);
holder.retry.setOnClickListener(clickListener);
ButtonHolder btnHolder;
if(holder.retry.getTag() != null) {
@@ -161,7 +159,7 @@ public class DownloadLogAdapter extends BaseAdapter {
static class Holder {
TextView icon;
- Button retry;
+ IconButton retry;
TextView title;
TextView type;
TextView date;
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 507d1adbc..1972e675e 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
@@ -11,6 +11,7 @@ import android.widget.Adapter;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -39,6 +40,9 @@ public class FeedItemlistAdapter extends BaseAdapter {
public static final int SELECTION_NONE = -1;
+ private final int playingBackGroundColor;
+ private final int normalBackGroundColor;
+
public FeedItemlistAdapter(Context context,
ItemAccess itemAccess,
ActionButtonCallback callback,
@@ -52,6 +56,9 @@ public class FeedItemlistAdapter extends BaseAdapter {
this.selectedItemIndex = SELECTION_NONE;
this.actionButtonUtils = new ActionButtonUtils(context);
this.makePlayedItemsTransparent = makePlayedItemsTransparent;
+
+ playingBackGroundColor = context.getResources().getColor(R.color.highlight_light);
+ normalBackGroundColor = context.getResources().getColor(android.R.color.transparent);
}
@Override
@@ -80,6 +87,8 @@ public class FeedItemlistAdapter extends BaseAdapter {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.feeditemlist_item, parent, false);
+ holder.container = (LinearLayout) convertView
+ .findViewById(R.id.container);
holder.title = (TextView) convertView
.findViewById(R.id.txtvItemname);
holder.lenSize = (TextView) convertView
@@ -174,9 +183,18 @@ public class FeedItemlistAdapter extends BaseAdapter {
holder.type.setImageBitmap(null);
holder.type.setVisibility(View.GONE);
}
+
+ if(media.isCurrentlyPlaying()) {
+ if(media.isCurrentlyPlaying()) {
+ holder.container.setBackgroundColor(playingBackGroundColor);
+ } else {
+ holder.container.setBackgroundColor(normalBackGroundColor);
+ }
+ }
}
- actionButtonUtils.configureActionButton(holder.butAction, item);
+ boolean isInQueue = itemAccess.isInQueue(item);
+ actionButtonUtils.configureActionButton(holder.butAction, item, isInQueue);
holder.butAction.setFocusable(false);
holder.butAction.setTag(item);
holder.butAction.setOnClickListener(butActionListener);
@@ -196,6 +214,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
};
static class Holder {
+ LinearLayout container;
TextView title;
TextView published;
TextView lenSize;
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 8593e0dde..3e4dd4deb 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
@@ -4,19 +4,18 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.support.v4.view.MotionEventCompat;
-import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
-import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
@@ -37,7 +36,6 @@ import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.UserPreferences;
-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.LongList;
@@ -62,6 +60,9 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
private FeedItem selectedItem;
+ private final int playingBackGroundColor;
+ private final int normalBackGroundColor;
+
public QueueRecyclerAdapter(MainActivity mainActivity,
ItemAccess itemAccess,
ActionButtonCallback actionButtonCallback,
@@ -73,6 +74,13 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
this.actionButtonCallback = actionButtonCallback;
this.itemTouchHelper = itemTouchHelper;
locked = UserPreferences.isQueueLocked();
+
+ if(UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
+ playingBackGroundColor = mainActivity.getResources().getColor(R.color.highlight_dark);
+ } else {
+ playingBackGroundColor = mainActivity.getResources().getColor(R.color.highlight_light);
+ }
+ normalBackGroundColor = mainActivity.getResources().getColor(android.R.color.transparent);
}
public void setLocked(boolean locked) {
@@ -108,6 +116,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
View.OnCreateContextMenuListener,
ItemTouchHelperViewHolder {
+ private final FrameLayout container;
private final ImageView dragHandle;
private final TextView placeholder;
private final ImageView cover;
@@ -122,6 +131,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
public ViewHolder(View v) {
super(v);
+ container = (FrameLayout) v.findViewById(R.id.container);
dragHandle = (ImageView) v.findViewById(R.id.drag_handle);
placeholder = (TextView) v.findViewById(R.id.txtvPlaceholder);
cover = (ImageView) v.findViewById(R.id.imgvCover);
@@ -249,9 +259,15 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
progressRight.setText(Converter.getDurationStringLong(media.getDuration()));
progressBar.setVisibility(View.GONE);
}
+
+ if(media.isCurrentlyPlaying()) {
+ container.setBackgroundColor(playingBackGroundColor);
+ } else {
+ container.setBackgroundColor(normalBackGroundColor);
+ }
}
- actionButtonUtils.configureActionButton(butSecondary, item);
+ actionButtonUtils.configureActionButton(butSecondary, item, true);
butSecondary.setFocusable(false);
butSecondary.setTag(item);
butSecondary.setOnClickListener(secondaryActionListener);
@@ -264,7 +280,6 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
.into(new CoverTarget(item.getFeed().getImageUri(), placeholder, cover));
}
-
}
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
index 3940eb8b6..5c24c2822 100644
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
@@ -49,7 +49,7 @@ public class OpmlExportWorker extends AsyncTask<Void, Void, Void> {
OpmlWriter opmlWriter = new OpmlWriter();
if (output == null) {
output = new File(
- UserPreferences.getDataFolder(context, EXPORT_DIR),
+ UserPreferences.getDataFolder(EXPORT_DIR),
DEFAULT_OUTPUT_NAME);
if (output.exists()) {
Log.w(TAG, "Overwriting previously exported file.");
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java
new file mode 100644
index 000000000..ed0db92a4
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java
@@ -0,0 +1,136 @@
+package de.danoeh.antennapod.dialog;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.support.annotation.Nullable;
+import android.util.Log;
+
+import com.afollestad.materialdialogs.MaterialDialog;
+
+import java.lang.ref.WeakReference;
+import java.util.concurrent.TimeUnit;
+
+import de.danoeh.antennapod.R;
+
+public class RatingDialog {
+
+ private static final String TAG = RatingDialog.class.getSimpleName();
+ private static final int AFTER_DAYS = 7;
+
+ private static WeakReference<Context> mContext;
+ private static SharedPreferences mPreferences;
+ private static Dialog mDialog;
+
+ private static final String PREFS_NAME = "RatingPrefs";
+ private static final String KEY_RATED = "KEY_WAS_RATED";
+ private static final String KEY_FIRST_START_DATE = "KEY_FIRST_HIT_DATE";
+
+ public static void init(Context context) {
+ mContext = new WeakReference<>(context);
+ mPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+
+ long firstDate = mPreferences.getLong(KEY_FIRST_START_DATE, 0);
+ if (firstDate == 0) {
+ resetStartDate();
+ }
+ }
+
+ public static void check() {
+ if (mDialog != null && mDialog.isShowing()) {
+ return;
+ }
+ if (shouldShow()) {
+ try {
+ mDialog = createDialog();
+ if (mDialog != null) {
+ mDialog.show();
+ }
+ } catch (Exception e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ }
+ }
+ }
+
+ public static void rateNow() {
+ Context context = mContext.get();
+ if(context == null) {
+ return;
+ }
+ final String appPackage = "de.danoeh.antennapod";
+ final Uri uri = Uri.parse("https://play.google.com/store/apps/details?id=" + appPackage);
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ saveRated();
+ }
+
+ public static boolean rated() {
+ return mPreferences.getBoolean(KEY_RATED, false);
+ }
+
+ public static void saveRated() {
+ mPreferences
+ .edit()
+ .putBoolean(KEY_RATED, true)
+ .apply();
+ }
+
+ private static void resetStartDate() {
+ mPreferences
+ .edit()
+ .putLong(KEY_FIRST_START_DATE, System.currentTimeMillis())
+ .apply();
+ }
+
+ private static boolean shouldShow() {
+ if (rated()) {
+ return false;
+ }
+
+ long now = System.currentTimeMillis();
+ long firstDate = mPreferences.getLong(KEY_FIRST_START_DATE, now);
+ long diff = now - firstDate;
+ long diffDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
+ if (diffDays >= AFTER_DAYS) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Nullable
+ private static MaterialDialog createDialog() {
+ Context context = mContext.get();
+ if(context == null) {
+ return null;
+ }
+ MaterialDialog dialog = new MaterialDialog.Builder(context)
+ .title(R.string.rating_title)
+ .content(R.string.rating_message)
+ .positiveText(R.string.rating_now_label)
+ .negativeText(R.string.rating_never_label)
+ .neutralText(R.string.rating_later_label)
+ .callback(new MaterialDialog.ButtonCallback() {
+ @Override
+ public void onPositive(MaterialDialog dialog) {
+ rateNow();
+ }
+
+ @Override
+ public void onNegative(MaterialDialog dialog) {
+ saveRated();
+ }
+
+ @Override
+ public void onNeutral(MaterialDialog dialog) {
+ resetStartDate();
+ }
+ })
+ .cancelListener(dialog1 -> resetStartDate())
+ .build();
+ return dialog;
+ }
+}
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 cdd6bc265..23b5be25a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -5,7 +5,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
-import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.LinearLayoutManager;
@@ -30,8 +29,10 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
-import de.danoeh.antennapod.core.asynctask.DownloadObserver;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.event.DownloadEvent;
+import de.danoeh.antennapod.core.event.DownloaderUpdate;
+import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -43,8 +44,10 @@ import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
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.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
+import de.greenrobot.event.EventBus;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
@@ -57,9 +60,7 @@ public class AllEpisodesFragment extends Fragment {
public static final String TAG = "AllEpisodesFragment";
- private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED |
- EventDistributor.FEED_LIST_UPDATE |
- EventDistributor.DOWNLOAD_QUEUED |
+ private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE |
EventDistributor.UNREAD_ITEMS_UPDATE |
EventDistributor.PLAYER_STATUS_UPDATE;
@@ -80,8 +81,6 @@ public class AllEpisodesFragment extends Fragment {
private AtomicReference<MainActivity> activity = new AtomicReference<MainActivity>();
- private DownloadObserver downloadObserver = null;
-
private boolean isUpdatingFeeds;
protected Subscription subscription;
@@ -101,10 +100,6 @@ public class AllEpisodesFragment extends Fragment {
super.onStart();
EventDistributor.getInstance().register(contentUpdate);
this.activity.set((MainActivity) getActivity());
- if (downloadObserver != null) {
- downloadObserver.setActivity(getActivity());
- downloadObserver.onResume();
- }
if (viewsCreated && itemsLoaded) {
onFragmentLoaded();
}
@@ -113,6 +108,7 @@ public class AllEpisodesFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
+ EventBus.getDefault().registerSticky(this);
loadItems();
registerForContextMenu(recyclerView);
}
@@ -120,6 +116,7 @@ public class AllEpisodesFragment extends Fragment {
@Override
public void onPause() {
super.onPause();
+ EventBus.getDefault().unregister(this);
saveScrollPosition();
unregisterForContextMenu(recyclerView);
}
@@ -180,9 +177,6 @@ public class AllEpisodesFragment extends Fragment {
listAdapter = null;
activity.set(null);
viewsCreated = false;
- if (downloadObserver != null) {
- downloadObserver.onPause();
- }
}
@@ -327,11 +321,10 @@ public class AllEpisodesFragment extends Fragment {
private void onFragmentLoaded() {
if (listAdapter == null) {
- listAdapter = new AllEpisodesRecycleAdapter(activity.get(), activity.get(), itemAccess,
- new DefaultActionButtonCallback(activity.get()), showOnlyNewEpisodes());
+ MainActivity mainActivity = activity.get();
+ listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess,
+ new DefaultActionButtonCallback(mainActivity), showOnlyNewEpisodes());
recyclerView.setAdapter(listAdapter);
- downloadObserver = new DownloadObserver(activity.get(), new Handler(), downloadObserverCallback);
- downloadObserver.onResume();
}
listAdapter.notifyDataSetChanged();
restoreScrollPosition();
@@ -339,21 +332,11 @@ public class AllEpisodesFragment extends Fragment {
updateShowOnlyEpisodesListViewState();
}
- private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
- @Override
- public void onContentChanged(List<Downloader> downloaderList) {
- AllEpisodesFragment.this.downloaderList = downloaderList;
- if (listAdapter != null) {
- listAdapter.notifyDataSetChanged();
- }
- }
- };
-
protected AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() {
@Override
public int getCount() {
- if (itemsLoaded) {
+ if (episodes != null) {
return episodes.size();
}
return 0;
@@ -361,7 +344,7 @@ public class AllEpisodesFragment extends Fragment {
@Override
public FeedItem getItem(int position) {
- if (itemsLoaded) {
+ if (episodes != null && position < episodes.size()) {
return episodes.get(position);
}
return null;
@@ -389,6 +372,39 @@ public class AllEpisodesFragment extends Fragment {
}
};
+ public void onEventMainThread(FeedItemEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ if(episodes == null || listAdapter == null) {
+ return;
+ }
+ for(int i=0, size = event.items.size(); i < size; i++) {
+ FeedItem item = event.items.get(i);
+ int pos = FeedItemUtil.indexOfItemWithId(episodes, item.getId());
+ if(pos >= 0) {
+ episodes.remove(pos);
+ episodes.add(pos, item);
+ listAdapter.notifyItemChanged(pos);
+ }
+ }
+ }
+
+
+ public void onEventMainThread(DownloadEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ DownloaderUpdate update = event.update;
+ downloaderList = update.downloaders;
+ if(update.feedIds.length > 0) {
+ if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
+ getActivity().supportInvalidateOptionsMenu();
+ }
+ }
+ if(update.mediaIds.length > 0) {
+ if(listAdapter != null) {
+ listAdapter.notifyDataSetChanged();
+ }
+ }
+ }
+
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
@@ -412,7 +428,7 @@ public class AllEpisodesFragment extends Fragment {
recyclerView.setVisibility(View.GONE);
progLoading.setVisibility(View.VISIBLE);
}
- subscription = Observable.defer(() -> Observable.just(loadData()))
+ subscription = Observable.fromCallable(() -> loadData())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> {
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 c5b582d3a..a5568b16e 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
@@ -156,7 +156,7 @@ public class CompletedDownloadsFragment extends ListFragment {
if (!itemsLoaded && viewCreated) {
setListShown(false);
}
- subscription = Observable.defer(() -> Observable.just(DBReader.getDownloadedItems()))
+ subscription = Observable.fromCallable(() -> DBReader.getDownloadedItems())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
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 669c6ac49..90cacd2e4 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
@@ -147,7 +147,7 @@ public class DownloadLogFragment extends ListFragment {
if(subscription != null) {
subscription.unsubscribe();
}
- subscription = Observable.defer(() -> Observable.just(DBReader.getDownloadLog()))
+ subscription = Observable.fromCallable(() -> DBReader.getDownloadLog())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
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 532516dda..65305df3d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
@@ -17,7 +17,6 @@ import de.danoeh.antennapod.core.event.FavoritesEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.greenrobot.event.EventBus;
/**
@@ -38,23 +37,11 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
protected String getPrefName() { return PREF_NAME; }
public void onEvent(FavoritesEvent event) {
- Log.d(TAG, "onEvent(" + event + ")");
+ Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
loadItems();
}
@Override
- public void onStart() {
- super.onStart();
- EventBus.getDefault().register(this);
- }
-
- @Override
- public void onStop() {
- super.onStop();
- EventBus.getDefault().unregister(this);
- }
-
- @Override
protected void resetViewState() {
super.resetViewState();
}
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 dc9f9740d..10d56d5cf 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
@@ -8,7 +8,6 @@ import android.content.res.TypedArray;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.util.Pair;
@@ -35,12 +34,16 @@ import android.widget.Toast;
import com.bumptech.glide.Glide;
+import org.apache.commons.lang3.ArrayUtils;
+
import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
-import de.danoeh.antennapod.core.asynctask.DownloadObserver;
+import de.danoeh.antennapod.core.event.DownloadEvent;
+import de.danoeh.antennapod.core.event.DownloaderUpdate;
+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;
@@ -72,9 +75,7 @@ public class ItemFragment extends Fragment {
private static final String TAG = "ItemFragment";
- private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED |
- EventDistributor.DOWNLOAD_QUEUED |
- EventDistributor.UNREAD_ITEMS_UPDATE;
+ private static final int EVENTS = EventDistributor.UNREAD_ITEMS_UPDATE;
private static final String ARG_FEEDITEM = "feeditem";
@@ -97,7 +98,6 @@ public class ItemFragment extends Fragment {
private FeedItem item;
private LongList queue;
private String webviewData;
- private DownloadObserver downloadObserver;
private List<Downloader> downloaderList;
private ViewGroup root;
@@ -263,11 +263,7 @@ public class ItemFragment extends Fragment {
public void onResume() {
super.onResume();
EventDistributor.getInstance().register(contentUpdate);
- EventBus.getDefault().register(this);
- if (downloadObserver != null) {
- downloadObserver.setActivity(getActivity());
- downloadObserver.onResume();
- }
+ EventBus.getDefault().registerSticky(this);
if(itemsLoaded) {
updateAppearance();
}
@@ -294,9 +290,6 @@ public class ItemFragment extends Fragment {
}
private void resetViewState() {
- if (downloadObserver != null) {
- downloadObserver.onPause();
- }
Toolbar toolbar = ((MainActivity) getActivity()).getToolbar();
toolbar.removeView(header);
}
@@ -319,8 +312,6 @@ public class ItemFragment extends Fragment {
"utf-8", "about:blank");
}
updateAppearance();
- downloadObserver = new DownloadObserver(getActivity(), new Handler(), downloadObserverCallback);
- downloadObserver.onResume();
}
private void updateAppearance() {
@@ -486,27 +477,41 @@ public class ItemFragment extends Fragment {
public void onEventMainThread(QueueEvent event) {
if(event.contains(itemID)) {
- updateAppearance();
+ load();
}
}
+ public void onEventMainThread(FeedItemEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ for(FeedItem item : event.items) {
+ if(itemID == item.getId()) {
+ load();
+ return;
+ }
+ }
+ }
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((arg & EVENTS) != 0) {
+ public void onEventMainThread(DownloadEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ DownloaderUpdate update = event.update;
+ downloaderList = update.downloaders;
+ if(item == null || item.getMedia() == null) {
+ return;
+ }
+ long mediaId = item.getMedia().getId();
+ if(ArrayUtils.contains(update.mediaIds, mediaId)) {
+ if (itemsLoaded && getActivity() != null) {
updateAppearance();
}
}
- };
+ }
- private final DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
+ private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
- public void onContentChanged(List<Downloader> downloaderList) {
- ItemFragment.this.downloaderList = downloaderList;
- if (itemsLoaded && getActivity() != null) {
- updateAppearance();
+ public void update(EventDistributor eventDistributor, Integer arg) {
+ if ((arg & EVENTS) != 0) {
+ load();
}
}
};
@@ -515,7 +520,7 @@ public class ItemFragment extends Fragment {
if(subscription != null) {
subscription.unsubscribe();
}
- subscription = Observable.defer(() -> Observable.just(loadInBackground()))
+ subscription = Observable.fromCallable(() -> loadInBackground())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
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 ba3dfc2af..7bdeb8a44 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
@@ -9,7 +9,6 @@ import android.graphics.Color;
import android.graphics.LightingColorFilter;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.ListFragment;
import android.support.v4.util.Pair;
@@ -46,17 +45,19 @@ import de.danoeh.antennapod.activity.FeedInfoActivity;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
-import de.danoeh.antennapod.core.asynctask.DownloadObserver;
import de.danoeh.antennapod.core.asynctask.FeedRemover;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
+import de.danoeh.antennapod.core.event.DownloadEvent;
+import de.danoeh.antennapod.core.event.DownloaderUpdate;
+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.Feed;
import de.danoeh.antennapod.core.feed.FeedEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedItemFilter;
import de.danoeh.antennapod.core.feed.FeedMedia;
-import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.glide.FastBlurTransformation;
import de.danoeh.antennapod.core.preferences.UserPreferences;
@@ -66,6 +67,7 @@ import de.danoeh.antennapod.core.storage.DBReader;
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;
@@ -85,9 +87,7 @@ import rx.schedulers.Schedulers;
public class ItemlistFragment extends ListFragment {
private static final String TAG = "ItemlistFragment";
- private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED
- | EventDistributor.DOWNLOAD_QUEUED
- | EventDistributor.UNREAD_ITEMS_UPDATE
+ private static final int EVENTS = EventDistributor.UNREAD_ITEMS_UPDATE
| EventDistributor.PLAYER_STATUS_UPDATE;
public static final String EXTRA_SELECTED_FEEDITEM = "extra.de.danoeh.antennapod.activity.selected_feeditem";
@@ -104,7 +104,6 @@ public class ItemlistFragment extends ListFragment {
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
- private DownloadObserver downloadObserver;
private List<Downloader> downloaderList;
private MoreContentListFooterUtil listFooter;
@@ -147,11 +146,7 @@ public class ItemlistFragment extends ListFragment {
public void onStart() {
super.onStart();
EventDistributor.getInstance().register(contentUpdate);
- EventBus.getDefault().register(this);
- if (downloadObserver != null) {
- downloadObserver.setActivity(getActivity());
- downloadObserver.onResume();
- }
+ EventBus.getDefault().registerSticky(this);
if (viewsCreated && itemsLoaded) {
onFragmentLoaded();
}
@@ -193,9 +188,6 @@ public class ItemlistFragment extends ListFragment {
adapter = null;
viewsCreated = false;
listFooter = null;
- if (downloadObserver != null) {
- downloadObserver.onPause();
- }
}
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = new MenuItemUtils.UpdateRefreshMenuItemChecker() {
@@ -394,29 +386,54 @@ public class ItemlistFragment extends ListFragment {
}
public void onEvent(QueueEvent event) {
- Log.d(TAG, "onEvent(" + event + ")");
+ Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
loadItems();
}
public void onEvent(FeedEvent event) {
- Log.d(TAG, "onEvent(" + event + ")");
+ Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
if(event.feedId == feedID) {
loadItems();
}
}
+ public void onEventMainThread(FeedItemEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ boolean queueChanged = false;
+ if(feed == null || feed.getItems() == null || adapter == null) {
+ return;
+ }
+ for(FeedItem item : event.items) {
+ int pos = FeedItemUtil.indexOfItemWithId(feed.getItems(), item.getId());
+ if(pos >= 0) {
+ loadItems();
+ return;
+ }
+ }
+ }
+
+ public void onEventMainThread(DownloadEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ DownloaderUpdate update = event.update;
+ downloaderList = update.downloaders;
+ if(update.feedIds.length > 0) {
+ updateProgressBarVisibility();
+ }
+ if(update.mediaIds.length > 0) {
+ if (adapter != null) {
+ adapter.notifyDataSetChanged();
+ }
+ }
+ }
+
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
if ((EVENTS & arg) != 0) {
Log.d(TAG, "Received contentUpdate Intent. arg " + arg);
- if ((EventDistributor.DOWNLOAD_QUEUED & arg) != 0) {
- updateProgressBarVisibility();
- } else {
- loadItems();
- updateProgressBarVisibility();
- }
+ loadItems();
+ updateProgressBarVisibility();
}
}
};
@@ -444,8 +461,6 @@ public class ItemlistFragment extends ListFragment {
setupFooterView();
adapter = new FeedItemlistAdapter(getActivity(), itemAccess, new DefaultActionButtonCallback(getActivity()), false, true);
setListAdapter(adapter);
- downloadObserver = new DownloadObserver(getActivity(), new Handler(), downloadObserverCallback);
- downloadObserver.onResume();
}
refreshHeaderView();
setListShown(true);
@@ -485,22 +500,10 @@ public class ItemlistFragment extends ListFragment {
txtvInformation.setVisibility(View.GONE);
}
} else {
-
txtvInformation.setVisibility(View.GONE);
}
}
-
- private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
- @Override
- public void onContentChanged(List<Downloader> downloaderList) {
- ItemlistFragment.this.downloaderList = downloaderList;
- if (adapter != null) {
- adapter.notifyDataSetChanged();
- }
- }
- };
-
private void setupHeaderView() {
if (getListView() == null || feed == null) {
Log.e(TAG, "Unable to setup listview: recyclerView = null or feed = null");
@@ -624,7 +627,7 @@ public class ItemlistFragment extends ListFragment {
subscription.unsubscribe();
}
- subscription = Observable.defer(() -> Observable.just(loadData()))
+ subscription = Observable.fromCallable(() -> loadData())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
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 d684c064c..b996e1cb3 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
@@ -14,14 +14,12 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
-import de.danoeh.antennapod.adapter.QueueRecyclerAdapter;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.greenrobot.event.EventBus;
/**
@@ -42,23 +40,11 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
protected String getPrefName() { return PREF_NAME; }
public void onEvent(QueueEvent event) {
- Log.d(TAG, "onEvent(" + event + ")");
+ Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
loadItems();
}
@Override
- public void onStart() {
- super.onStart();
- EventBus.getDefault().register(this);
- }
-
- @Override
- public void onStop() {
- super.onStop();
- EventBus.getDefault().unregister(this);
- }
-
- @Override
protected void resetViewState() {
super.resetViewState();
}
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 d7ffa3e23..b47a197c3 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
@@ -3,7 +3,6 @@ package de.danoeh.antennapod.fragment;
import android.app.Activity;
import android.content.res.TypedArray;
import android.os.Bundle;
-import android.os.Handler;
import android.support.v4.app.ListFragment;
import android.support.v4.util.Pair;
import android.support.v4.view.MenuItemCompat;
@@ -21,7 +20,8 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
-import de.danoeh.antennapod.core.asynctask.DownloadObserver;
+import de.danoeh.antennapod.core.event.DownloadEvent;
+import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
@@ -52,12 +52,20 @@ public class PlaybackHistoryFragment extends ListFragment {
private AtomicReference<Activity> activity = new AtomicReference<Activity>();
- private DownloadObserver downloadObserver;
private List<Downloader> downloaderList;
private Subscription subscription;
@Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ this.activity.set(activity);
+ if (viewsCreated && itemsLoaded) {
+ onFragmentLoaded();
+ }
+ }
+
+ @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
@@ -65,8 +73,26 @@ public class PlaybackHistoryFragment extends ListFragment {
}
@Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ // add padding
+ final ListView lv = getListView();
+ lv.setClipToPadding(false);
+ final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
+ lv.setPadding(0, vertPadding, 0, vertPadding);
+
+ viewsCreated = true;
+ if (itemsLoaded) {
+ onFragmentLoaded();
+ }
+ }
+
+
+ @Override
public void onResume() {
super.onResume();
+ EventBus.getDefault().registerSticky(this);
loadItems();
}
@@ -74,14 +100,18 @@ public class PlaybackHistoryFragment extends ListFragment {
public void onStart() {
super.onStart();
EventDistributor.getInstance().register(contentUpdate);
- EventBus.getDefault().register(this);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ EventBus.getDefault().unregister(this);
}
@Override
public void onStop() {
super.onStop();
EventDistributor.getInstance().unregister(contentUpdate);
- EventBus.getDefault().unregister(this);
if(subscription != null) {
subscription.unsubscribe();
}
@@ -97,41 +127,18 @@ public class PlaybackHistoryFragment extends ListFragment {
}
@Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- this.activity.set(activity);
- if (downloadObserver != null) {
- downloadObserver.setActivity(activity);
- downloadObserver.onResume();
- }
- if (viewsCreated && itemsLoaded) {
- onFragmentLoaded();
- }
- }
-
- @Override
public void onDestroyView() {
super.onDestroyView();
adapter = null;
viewsCreated = false;
- if (downloadObserver != null) {
- downloadObserver.onPause();
- }
}
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- // add padding
- final ListView lv = getListView();
- lv.setClipToPadding(false);
- final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
- lv.setPadding(0, vertPadding, 0, vertPadding);
-
- viewsCreated = true;
- if (itemsLoaded) {
- onFragmentLoaded();
+ public void onEvent(DownloadEvent event) {
+ Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
+ DownloaderUpdate update = event.update;
+ downloaderList = update.downloaders;
+ if (adapter != null) {
+ adapter.notifyDataSetChanged();
}
}
@@ -205,24 +212,12 @@ public class PlaybackHistoryFragment extends ListFragment {
// it harder to read.
adapter = new FeedItemlistAdapter(getActivity(), itemAccess, new DefaultActionButtonCallback(activity.get()), true, false);
setListAdapter(adapter);
- downloadObserver = new DownloadObserver(activity.get(), new Handler(), downloadObserverCallback);
- downloadObserver.onResume();
}
setListShown(true);
adapter.notifyDataSetChanged();
getActivity().supportInvalidateOptionsMenu();
}
- private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
- @Override
- public void onContentChanged(List<Downloader> downloaderList) {
- PlaybackHistoryFragment.this.downloaderList = downloaderList;
- if (adapter != null) {
- adapter.notifyDataSetChanged();
- }
- }
- };
-
private FeedItemlistAdapter.ItemAccess itemAccess = new FeedItemlistAdapter.ItemAccess() {
@Override
public boolean isInQueue(FeedItem item) {
@@ -257,7 +252,7 @@ public class PlaybackHistoryFragment extends ListFragment {
if(subscription != null) {
subscription.unsubscribe();
}
- subscription = Observable.defer(() -> Observable.just(loadData()))
+ subscription = Observable.fromCallable(() -> loadData())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
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 610490298..e13fd76b3 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -4,7 +4,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
-import android.os.Handler;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
@@ -25,15 +24,15 @@ import android.widget.Toast;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
-import java.util.Collections;
import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.adapter.QueueRecyclerAdapter;
-import de.danoeh.antennapod.core.asynctask.DownloadObserver;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.event.DownloadEvent;
+import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
@@ -68,7 +67,6 @@ public class QueueFragment extends Fragment {
public static final String TAG = "QueueFragment";
private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED |
- EventDistributor.DOWNLOAD_QUEUED |
EventDistributor.PLAYER_STATUS_UPDATE;
private TextView infoBar;
@@ -86,13 +84,6 @@ public class QueueFragment extends Fragment {
private static final String PREF_SCROLL_POSITION = "scroll_position";
private static final String PREF_SCROLL_OFFSET = "scroll_offset";
- private DownloadObserver downloadObserver = null;
-
- /**
- * Download observer updates won't result in an upate of the list adapter if this is true.
- */
- private boolean blockDownloadObserverUpdate = false;
-
private Subscription subscription;
private LinearLayoutManager layoutManager;
private ItemTouchHelper itemTouchHelper;
@@ -108,10 +99,6 @@ public class QueueFragment extends Fragment {
@Override
public void onStart() {
super.onStart();
- if (downloadObserver != null) {
- downloadObserver.setActivity(getActivity());
- downloadObserver.onResume();
- }
if (queue != null) {
onFragmentLoaded();
}
@@ -123,7 +110,7 @@ public class QueueFragment extends Fragment {
recyclerView.setAdapter(recyclerAdapter);
loadItems();
EventDistributor.getInstance().register(contentUpdate);
- EventBus.getDefault().register(this);
+ EventBus.getDefault().registerSticky(this);
}
@Override
@@ -138,7 +125,10 @@ public class QueueFragment extends Fragment {
}
public void onEventMainThread(QueueEvent event) {
- Log.d(TAG, "onEvent(" + event + ")");
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ if(queue == null || recyclerAdapter == null) {
+ return;
+ }
switch(event.action) {
case ADDED:
queue.add(event.position, event.item);
@@ -163,17 +153,17 @@ public class QueueFragment extends Fragment {
recyclerAdapter.notifyDataSetChanged();
break;
case MOVED:
- int from = FeedItemUtil.indexOfItemWithId(queue, event.item.getId());
- int to = event.position;
- queue.add(to, queue.remove(from));
- recyclerAdapter.notifyItemMoved(from, to);
- break;
+ return;
}
+ saveScrollPosition();
onFragmentLoaded();
}
public void onEventMainThread(FeedItemEvent event) {
- Log.d(TAG, "onEvent(" + event + ")");
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ if(queue == null || recyclerAdapter == null) {
+ return;
+ }
for(int i=0, size = event.items.size(); i < size; i++) {
FeedItem item = event.items.get(i);
int pos = FeedItemUtil.indexOfItemWithId(queue, item.getId());
@@ -185,6 +175,21 @@ public class QueueFragment extends Fragment {
}
}
+ public void onEventMainThread(DownloadEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ DownloaderUpdate update = event.update;
+ downloaderList = update.downloaders;
+ if (update.feedIds.length > 0) {
+ if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
+ getActivity().supportInvalidateOptionsMenu();
+ }
+ } else if (update.mediaIds.length > 0) {
+ if (recyclerAdapter != null) {
+ recyclerAdapter.notifyDataSetChanged();
+ }
+ }
+ }
+
private void saveScrollPosition() {
int firstItem = layoutManager.findFirstVisibleItemPosition();
View firstItemView = layoutManager.findViewByPosition(firstItem);
@@ -208,20 +213,11 @@ public class QueueFragment extends Fragment {
float offset = prefs.getFloat(PREF_SCROLL_OFFSET, 0.0f);
if (position > 0 || offset > 0) {
layoutManager.scrollToPositionWithOffset(position, (int) offset);
- // restore once, then forget
- SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(PREF_SCROLL_POSITION, 0);
- editor.putFloat(PREF_SCROLL_OFFSET, 0.0f);
- editor.commit();
}
}
private void resetViewState() {
recyclerAdapter = null;
- blockDownloadObserverUpdate = false;
- if (downloadObserver != null) {
- downloadObserver.onPause();
- }
}
@Override
@@ -333,12 +329,27 @@ public class QueueFragment extends Fragment {
return super.onContextItemSelected(item);
}
- try {
- return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
- return true;
+ switch(item.getItemId()) {
+ case R.id.move_to_top_item:
+ int position = FeedItemUtil.indexOfItemWithId(queue, selectedItem.getId());
+ queue.add(0, queue.remove(position));
+ recyclerAdapter.notifyItemMoved(position, 0);
+ DBWriter.moveQueueItemToTop(selectedItem.getId(), true);
+ return true;
+ case R.id.move_to_bottom_item:
+ position = FeedItemUtil.indexOfItemWithId(queue, selectedItem.getId());
+ queue.add(queue.size()-1, queue.remove(position));
+ recyclerAdapter.notifyItemMoved(position, queue.size()-1);
+ DBWriter.moveQueueItemToBottom(selectedItem.getId(), true);
+ return true;
+ default:
+ try {
+ return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
+ } catch (DownloadRequestException e) {
+ e.printStackTrace();
+ Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
+ return true;
+ }
}
}
@@ -367,7 +378,7 @@ public class QueueFragment extends Fragment {
Log.d(TAG, "move(" + from + ", " + to + ")");
queue.add(to, queue.remove(from));
recyclerAdapter.notifyItemMoved(from, to);
- DBWriter.moveQueueItem(from, to, false);
+ DBWriter.moveQueueItem(from, to, true);
return true;
}
@@ -445,8 +456,6 @@ public class QueueFragment extends Fragment {
recyclerAdapter = new QueueRecyclerAdapter(activity, itemAccess,
new DefaultActionButtonCallback(activity), itemTouchHelper);
recyclerView.setAdapter(recyclerAdapter);
- downloadObserver = new DownloadObserver(activity, new Handler(), downloadObserverCallback);
- downloadObserver.onResume();
}
if(queue == null || queue.size() == 0) {
recyclerView.setVisibility(View.GONE);
@@ -480,16 +489,6 @@ public class QueueFragment extends Fragment {
infoBar.setText(info);
}
- private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
- @Override
- public void onContentChanged(List<Downloader> downloaderList) {
- QueueFragment.this.downloaderList = downloaderList;
- if (recyclerAdapter != null && !blockDownloadObserverUpdate) {
- recyclerAdapter.notifyDataSetChanged();
- }
- }
- };
-
private QueueRecyclerAdapter.ItemAccess itemAccess = new QueueRecyclerAdapter.ItemAccess() {
@Override
public int getCount() {
@@ -498,7 +497,10 @@ public class QueueFragment extends Fragment {
@Override
public FeedItem getItem(int position) {
- return queue != null ? queue.get(position) : null;
+ if(queue != null && position < queue.size()) {
+ return queue.get(position);
+ }
+ return null;
}
@Override
@@ -551,6 +553,7 @@ public class QueueFragment extends Fragment {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
if ((arg & EVENTS) != 0) {
+ Log.d(TAG, "arg: " + arg);
loadItems();
if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
getActivity().supportInvalidateOptionsMenu();
@@ -560,6 +563,7 @@ public class QueueFragment extends Fragment {
};
private void loadItems() {
+ Log.d(TAG, "loadItems()");
if(subscription != null) {
subscription.unsubscribe();
}
@@ -568,7 +572,7 @@ public class QueueFragment extends Fragment {
txtvEmpty.setVisibility(View.GONE);
progLoading.setVisibility(View.VISIBLE);
}
- subscription = Observable.defer(() -> Observable.just(DBReader.getQueue()))
+ subscription = Observable.fromCallable(() -> DBReader.getQueue())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(items -> {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
index 544bdfc43..d81d18640 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
@@ -1,7 +1,6 @@
package de.danoeh.antennapod.fragment;
import android.os.Bundle;
-import android.os.Handler;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.View;
@@ -12,7 +11,8 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.DownloadlistAdapter;
-import de.danoeh.antennapod.core.asynctask.DownloadObserver;
+import de.danoeh.antennapod.core.event.DownloadEvent;
+import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
@@ -20,25 +20,18 @@ 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.storage.DownloadRequester;
+import de.greenrobot.event.EventBus;
/**
* Displays all running downloads and provides actions to cancel them
*/
public class RunningDownloadsFragment extends ListFragment {
+
private static final String TAG = "RunningDownloadsFrag";
- private DownloadObserver downloadObserver;
+ private DownloadlistAdapter adapter;
private List<Downloader> downloaderList;
-
- @Override
- public void onDetach() {
- super.onDetach();
- if (downloadObserver != null) {
- downloadObserver.onPause();
- }
- }
-
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -49,20 +42,39 @@ public class RunningDownloadsFragment extends ListFragment {
final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
lv.setPadding(0, vertPadding, 0, vertPadding);
- final DownloadlistAdapter downloadlistAdapter = new DownloadlistAdapter(getActivity(), itemAccess);
- setListAdapter(downloadlistAdapter);
+ adapter = new DownloadlistAdapter(getActivity(), itemAccess);
+ setListAdapter(adapter);
+ }
- downloadObserver = new DownloadObserver(getActivity(), new Handler(), new DownloadObserver.Callback() {
- @Override
- public void onContentChanged(List<Downloader> downloaderList) {
- Log.d(TAG, "onContentChanged: downloaderList.size() == " + downloaderList.size());
- RunningDownloadsFragment.this.downloaderList = downloaderList;
- downloadlistAdapter.notifyDataSetChanged();
- }
- });
- downloadObserver.onResume();
+ @Override
+ public void onResume() {
+ super.onResume();
+ EventBus.getDefault().registerSticky(this);
}
+ @Override
+ public void onPause() {
+ super.onPause();
+ EventBus.getDefault().unregister(this);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ setListAdapter(null);
+ adapter = null;
+ }
+
+ public void onEvent(DownloadEvent event) {
+ Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
+ DownloaderUpdate update = event.update;
+ downloaderList = update.downloaders;
+ if (adapter != null) {
+ adapter.notifyDataSetChanged();
+ }
+ }
+
+
private DownloadlistAdapter.ItemAccess itemAccess = new DownloadlistAdapter.ItemAccess() {
@Override
public int getCount() {
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 edd8cdd1a..43354ad28 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
@@ -204,7 +204,7 @@ public class SearchFragment extends ListFragment {
if (viewCreated && !itemsLoaded) {
setListShown(false);
}
- subscription = Observable.defer(() -> Observable.just(performSearch()))
+ subscription = Observable.fromCallable(() -> performSearch())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
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 3fa1048c0..0197cc88c 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
@@ -186,11 +186,6 @@ public class FeedItemMenuHandler {
GpodnetPreferences.enqueueEpisodeAction(actionNew);
}
break;
- case R.id.move_to_top_item:
- DBWriter.moveQueueItemToTop(selectedItem.getId(), true);
- return true;
- case R.id.move_to_bottom_item:
- DBWriter.moveQueueItemToBottom(selectedItem.getId(), true);
case R.id.add_to_queue_item:
DBWriter.addQueueItem(context, selectedItem);
break;
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 f729ef807..94f5d822e 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.preferences;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.TimePickerDialog;
import android.content.Context;
@@ -7,6 +8,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
+import android.net.Uri;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
@@ -16,8 +18,10 @@ import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
+import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
+import android.text.Html;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.util.Log;
@@ -31,7 +35,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import de.danoeh.antennapod.BuildConfig;
+import de.danoeh.antennapod.CrashReportWriter;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.AboutActivity;
import de.danoeh.antennapod.activity.DirectoryChooserActivity;
@@ -41,6 +45,8 @@ import de.danoeh.antennapod.activity.PreferenceActivityGingerbread;
import de.danoeh.antennapod.asynctask.OpmlExportWorker;
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.core.util.flattr.FlattrUtils;
import de.danoeh.antennapod.dialog.AuthenticationDialog;
import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog;
@@ -50,9 +56,11 @@ import de.danoeh.antennapod.dialog.VariableSpeedDialog;
/**
* Sets up a preference UI that lets the user change user preferences.
*/
+
public class PreferenceController implements SharedPreferences.OnSharedPreferenceChangeListener {
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";
@@ -158,21 +166,22 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
}
);
-
- ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener(
- new Preference.OnPreferenceClickListener() {
-
- @Override
- public boolean onPreferenceClick(Preference preference) {
- activity.startActivityForResult(
- new Intent(activity,
- DirectoryChooserActivity.class),
- DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED
- );
- return true;
- }
- }
- );
+ ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR)
+ .setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ showChooseDataFolderDialog();
+ } else {
+ Intent intent = new Intent(activity, DirectoryChooserActivity.class);
+ activity.startActivityForResult(intent,
+ DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED);
+ }
+ return true;
+ }
+ }
+ );
ui.findPreference(UserPreferences.PREF_THEME)
.setOnPreferenceChangeListener(
new Preference.OnPreferenceChangeListener() {
@@ -247,7 +256,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
setParallelDownloadsText(value);
return true;
}
- } catch(NumberFormatException e) {
+ } catch (NumberFormatException e) {
return false;
}
}
@@ -256,17 +265,19 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
);
// validate and set correct value: number of downloads between 1 and 50 (inclusive)
- final EditText ev = ((EditTextPreference)ui.findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS)).getEditText();
+ final EditText ev = ((EditTextPreference) ui.findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS)).getEditText();
ev.addTextChangedListener(new TextWatcher() {
@Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
@Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {}
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
@Override
public void afterTextChanged(Editable s) {
- if(s.length() > 0) {
+ if (s.length() > 0) {
try {
int value = Integer.valueOf(s.toString());
if (value <= 0) {
@@ -274,7 +285,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
} else if (value > 50) {
ev.setText("50");
}
- } catch(NumberFormatException e) {
+ } catch (NumberFormatException e) {
ev.setText("6");
}
ev.setSelection(ev.getText().length());
@@ -379,11 +390,23 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
}
);
+ ui.findPreference("prefSendCrashReport").setOnPreferenceClickListener(preference -> {
+ Intent emailIntent = new Intent(Intent.ACTION_SEND);
+ emailIntent.setType("text/plain");
+ String to[] = { "Martin.Fietz@gmail.com" };
+ emailIntent .putExtra(Intent.EXTRA_EMAIL, to);
+ // the attachment
+ emailIntent .putExtra(Intent.EXTRA_STREAM, Uri.fromFile(CrashReportWriter.getFile()));
+ // the mail subject
+ emailIntent .putExtra(Intent.EXTRA_SUBJECT, "AntennaPod Crash Report");
+ String intentTitle = ui.getActivity().getString(R.string.send_email);
+ ui.getActivity().startActivity(Intent.createChooser(emailIntent, intentTitle));
+ return true;
+ });
buildEpisodeCleanupPreference();
buildSmartMarkAsPlayedPreference();
buildAutodownloadSelectedNetworsPreference();
- setSelectedNetworksEnabled(UserPreferences
- .isEnableAutodownloadWifiFilter());
+ setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter());
}
public void onResume() {
@@ -394,16 +417,37 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
updateGpodnetPreferenceScreen();
}
+ @SuppressLint("NewApi")
public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) {
- String dir = data
- .getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Setting data folder");
- UserPreferences.setDataFolder(dir);
+ if (resultCode == Activity.RESULT_OK &&
+ requestCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) {
+ String dir = data.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR);
+
+ File path = new File(dir);
+ String message = null;
+ final Context context= ui.getActivity().getApplicationContext();
+ if(!path.exists()) {
+ message = String.format(context.getString(R.string.folder_does_not_exist_error), dir);
+ } else if(!path.canRead()) {
+ message = String.format(context.getString(R.string.folder_not_readable_error), dir);
+ } else if(!path.canWrite()) {
+ message = String.format(context.getString(R.string.folder_not_writable_error), dir);
+ }
+
+ if(message == null) {
+ Log.d(TAG, "Setting data folder: " + dir);
+ UserPreferences.setDataFolder(dir);
+ setDataFolderText();
+ } else {
+ AlertDialog.Builder ab = new AlertDialog.Builder(ui.getActivity());
+ ab.setMessage(message);
+ ab.setPositiveButton(android.R.string.ok, null);
+ ab.show();
+ }
}
}
+
private void updateGpodnetPreferenceScreen() {
final boolean loggedIn = GpodnetPreferences.loggedIn();
ui.findPreference(PreferenceController.PREF_GPODNET_LOGIN).setEnabled(!loggedIn);
@@ -499,6 +543,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY)
.setEnabled(UserPreferences.isEnableAutodownload());
+ ui.findPreference("prefSendCrashReport").setEnabled(CrashReportWriter.getFile().exists());
+
if (Build.VERSION.SDK_INT >= 16) {
ui.findPreference(UserPreferences.PREF_SONIC).setEnabled(true);
} else {
@@ -530,7 +576,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
private void setDataFolderText() {
- File f = UserPreferences.getDataFolder(ui.getActivity(), null);
+ File f = UserPreferences.getDataFolder(null);
if (f != null) {
ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR)
.setSummary(f.getAbsolutePath());
@@ -564,9 +610,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
);
boolean newValue = ((CheckBoxPreference) preference)
.isChecked();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Selected network " + key
- + ". New state: " + newValue);
+ Log.d(TAG, "Selected network " + key + ". New state: " + newValue);
int index = prefValuesList.indexOf(key);
if (index >= 0 && newValue == false) {
@@ -649,6 +693,47 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
builder.create().show();
}
+ private void showChooseDataFolderDialog() {
+ Context context = ui.getActivity();
+ String dataFolder = UserPreferences.getDataFolder(null).getAbsolutePath();
+ int selectedIndex = -1;
+ File[] mediaDirs = ContextCompat.getExternalFilesDirs(context, null);
+ String[] folders = new String[mediaDirs.length];
+ CharSequence[] choices = new CharSequence[mediaDirs.length];
+ for(int i=0; i < mediaDirs.length; i++) {
+ String path = folders[i] = mediaDirs[i].getAbsolutePath();
+ if(dataFolder.equals(path)) {
+ selectedIndex = i;
+ }
+ int index = path.indexOf("Android");
+ if(index >= 0) {
+ choices[i] = path.substring(0, index);
+ } else {
+ choices[i] = path;
+ }
+ long bytes = StorageUtils.getFreeSpaceAvailable();
+ String freeSpace = String.format(context.getString(R.string.free_space_label),
+ Converter.byteToString(bytes));
+ choices[i] = Html.fromHtml("<html><small>" + choices[i]
+ + " [" + freeSpace + "]" + "</small></html>");
+ }
+ MaterialDialog dialog = new MaterialDialog.Builder(ui.getActivity())
+ .title(R.string.choose_data_directory)
+ .content(R.string.choose_data_directory_message)
+ .items(choices)
+ .itemsCallbackSingleChoice(selectedIndex, (dialog1, itemView, which, text) -> {
+ String folder = folders[which];
+ Log.d(TAG, "data folder: " + folder);
+ UserPreferences.setDataFolder(folder);
+ setDataFolderText();
+ return true;
+ })
+ .negativeText(R.string.cancel_label)
+ .cancelable(true)
+ .build();
+ dialog.show();
+ }
+
private void showUpdateIntervalTimePreferencesDialog() {
final Context context = ui.getActivity();
diff --git a/app/src/main/res/layout/downloadlog_item.xml b/app/src/main/res/layout/downloadlog_item.xml
index c6a34a517..20d879933 100644
--- a/app/src/main/res/layout/downloadlog_item.xml
+++ b/app/src/main/res/layout/downloadlog_item.xml
@@ -20,7 +20,7 @@
tools:text="[Icon]"
android:gravity="center" />
- <Button
+ <com.joanzapata.iconify.widget.IconButton
android:id="@+id/btnRetry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -28,6 +28,7 @@
android:layout_alignLeft="@id/txtvIcon"
android:layout_alignRight="@id/txtvIcon"
android:layout_marginTop="8dp"
+ android:text="{fa-repeat}"
tools:text="↻" />
<TextView
diff --git a/app/src/main/res/layout/feeditemlist_item.xml b/app/src/main/res/layout/feeditemlist_item.xml
index 6b7c45978..d2b85e7df 100644
--- a/app/src/main/res/layout/feeditemlist_item.xml
+++ b/app/src/main/res/layout/feeditemlist_item.xml
@@ -1,14 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="@dimen/listitem_threeline_height"
android:orientation="horizontal"
tools:background="@android:color/darker_gray">
<RelativeLayout
-
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
@@ -103,12 +104,10 @@
android:indeterminate="false"
/>
-
-
</RelativeLayout>
<include layout="@layout/vertical_list_divider"/>
<include layout="@layout/secondary_action"/>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/app/src/main/res/layout/new_episodes_listitem.xml b/app/src/main/res/layout/new_episodes_listitem.xml
index 7a5652c45..cde1b4aa6 100644
--- a/app/src/main/res/layout/new_episodes_listitem.xml
+++ b/app/src/main/res/layout/new_episodes_listitem.xml
@@ -1,11 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout
+ android:id="@+id/container"
+ xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+<LinearLayout
+ android:layout_width="match_parent"
android:layout_height="@dimen/listitem_threeline_height"
- android:orientation="horizontal"
android:background="?attr/selectableItemBackground"
+ android:orientation="horizontal"
tools:background="@android:color/darker_gray">
<RelativeLayout
@@ -127,4 +133,6 @@
<include layout="@layout/secondary_action" />
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
+
+</FrameLayout>
diff --git a/app/src/main/res/layout/queue_listitem.xml b/app/src/main/res/layout/queue_listitem.xml
index 8572f5e05..d950f11d2 100644
--- a/app/src/main/res/layout/queue_listitem.xml
+++ b/app/src/main/res/layout/queue_listitem.xml
@@ -1,14 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
+<FrameLayout
+ android:id="@+id/container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+<LinearLayout
+ android:layout_width="match_parent"
android:layout_height="@dimen/listitem_threeline_height"
+ android:background="?attr/selectableItemBackground"
android:orientation="horizontal"
android:paddingLeft="8dp"
android:gravity="center_vertical"
- android:background="?attr/selectableItemBackground"
tools:background="@android:color/darker_gray" >
<ImageView
@@ -135,4 +140,6 @@
<include layout="@layout/secondary_action"/>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
+
+</FrameLayout>
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index 38350155a..e9e9d48f7 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -90,6 +90,12 @@
android:summary="@string/pref_unpauseOnBluetoothReconnect_sum"
android:title="@string/pref_unpauseOnBluetoothReconnect_title"/>
<CheckBoxPreference
+ android:defaultValue="false"
+ android:enabled="true"
+ android:key="prefHardwareForwardButtonSkips"
+ android:summary="@string/pref_hardwareForwardButtonSkips_sum"
+ android:title="@string/pref_hardwareForwardButtonSkips_title"/>
+ <CheckBoxPreference
android:defaultValue="true"
android:enabled="true"
android:key="prefFollowQueue"
@@ -245,6 +251,10 @@
<Preference
android:key="prefAbout"
android:title="@string/about_pref"/>
+ <Preference
+ android:key="prefSendCrashReport"
+ android:title="@string/crash_report_title"
+ android:summary="@string/crash_report_sum"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/experimental_pref">