diff options
Diffstat (limited to 'app/src/main/java/de/danoeh')
34 files changed, 868 insertions, 853 deletions
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 559fa0574..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,370 +1,336 @@ package de.danoeh.antennapod.activity; import android.app.Activity; -import android.app.AlertDialog; -import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.os.Environment; import android.os.FileObserver; import android.support.v4.app.NavUtils; import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.Menu; 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, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, - int which) { - dialog.dismiss(); - } - }); - adb.setPositiveButton(R.string.confirm_label, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, - int which) { - dialog.dismiss(); - returnSelectedFolder(); - } - }); - adb.create().show(); - } - }); - - butCancel.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - setResult(Activity.RESULT_CANCELED); - finish(); - } - }); - - listDirectories.setOnItemClickListener(new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView<?> adapter, View view, - int position, long id) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Selected index: " + position); - if (filesInDir != null && position >= 0 - && position < filesInDir.length) { - changeDirectory(filesInDir[position]); - } - } - }); - - butNavUp.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - File parent = null; - if (selectedDir != null - && (parent = selectedDir.getParentFile()) != null) { - changeDirectory(parent); - } - } - }); - - filenames = new ArrayList<String>(); - listDirectoriesAdapter = new ArrayAdapter<String>(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) { + 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) -> { + dialog.dismiss(); + returnSelectedFolder(); + }); + adb.create().show(); + } + }); + + butCancel.setOnClickListener(v -> { + setResult(Activity.RESULT_CANCELED); + finish(); + }); + + listDirectories.setOnItemClickListener((adapter, view, position, id) -> { + Log.d(TAG, "Selected index: " + position); + if (filesInDir != null && position >= 0 + && position < filesInDir.length) { + changeDirectory(filesInDir[position]); + } + }); + + butNavUp.setOnClickListener(v -> { + File parent = null; + if (selectedDir != null + && (parent = selectedDir.getParentFile()) != null) { + changeDirectory(parent); + } + }); + + 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 14128bec9..211b895d0 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -1,7 +1,6 @@ package de.danoeh.antennapod.activity; import android.annotation.TargetApi; -import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; @@ -21,6 +20,7 @@ import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.app.AlertDialog; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.ContextMenu; @@ -42,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; @@ -78,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"; @@ -642,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/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java index e34b4dc67..c53a5257b 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java @@ -1,6 +1,5 @@ package de.danoeh.antennapod.activity; -import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.PixelFormat; @@ -8,6 +7,7 @@ import android.media.AudioManager; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; @@ -19,6 +19,8 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; +import com.afollestad.materialdialogs.MaterialDialog; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; @@ -291,49 +293,40 @@ public abstract class MediaplayerActivity extends ActionBarActivity switch (item.getItemId()) { case R.id.disable_sleeptimer_item: if (controller.serviceAvailable()) { - AlertDialog.Builder stDialog = new AlertDialog.Builder(this); - stDialog.setTitle(R.string.sleep_timer_label); - stDialog.setMessage(getString(R.string.time_left_label) + + MaterialDialog.Builder stDialog = new MaterialDialog.Builder(this); + stDialog.title(R.string.sleep_timer_label); + stDialog.content(getString(R.string.time_left_label) + Converter.getDurationStringLong((int) controller .getSleepTimerTimeLeft())); - stDialog.setPositiveButton( - R.string.disable_sleeptimer_label, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, - int which) { - dialog.dismiss(); - controller.disableSleepTimer(); - } - } - ); - stDialog.setNegativeButton(R.string.cancel_label, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, - int which) { - dialog.dismiss(); - } - } - ); - stDialog.create().show(); + stDialog.positiveText(R.string.disable_sleeptimer_label); + stDialog.negativeText(R.string.cancel_label); + stDialog.callback(new MaterialDialog.ButtonCallback() { + @Override + public void onPositive(MaterialDialog dialog) { + dialog.dismiss(); + controller.disableSleepTimer(); + } + + @Override + public void onNegative(MaterialDialog dialog) { + dialog.dismiss(); + } + }); + stDialog.build().show(); } break; case R.id.set_sleeptimer_item: if (controller.serviceAvailable()) { - SleepTimerDialog td = new SleepTimerDialog(this, 0, 0) { + SleepTimerDialog td = new SleepTimerDialog(this) { @Override public void onTimerSet(long millis, boolean shakeToReset, boolean vibrate) { controller.setSleepTimer(millis, shakeToReset, vibrate); } }; - td.show(); - - break; - + td.createNewDialog().show(); } + break; case R.id.visit_website_item: Uri uri = Uri.parse(media.getWebsiteLink()); startActivity(new Intent(Intent.ACTION_VIEW, uri)); @@ -500,19 +493,13 @@ public abstract class MediaplayerActivity extends ActionBarActivity AlertDialog.Builder builder = new AlertDialog.Builder(MediaplayerActivity.this); builder.setTitle(R.string.pref_fast_forward); builder.setSingleChoiceItems(choices, checked, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - choice = values[which]; - } + (dialog, which) -> { + choice = values[which]; }); builder.setNegativeButton(R.string.cancel_label, null); - builder.setPositiveButton(R.string.confirm_label, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - UserPreferences.setPrefFastForwardSecs(choice); - txtvFF.setText(String.valueOf(choice)); - } + builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { + UserPreferences.setPrefFastForwardSecs(choice); + txtvFF.setText(String.valueOf(choice)); }); builder.create().show(); return true; 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 a629b8758..b32389bd9 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java @@ -1,6 +1,5 @@ package de.danoeh.antennapod.activity; -import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; @@ -9,6 +8,7 @@ import android.os.Bundle; import android.os.Looper; import android.support.v4.app.NavUtils; import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; @@ -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/activity/OpmlImportFromIntentActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java index f7e9256c0..46e5f0e8e 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java @@ -1,8 +1,8 @@ package de.danoeh.antennapod.activity; -import android.app.AlertDialog; import android.net.Uri; import android.os.Bundle; +import android.support.v7.app.AlertDialog; import android.util.Log; import de.danoeh.antennapod.core.preferences.UserPreferences; 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/ChapterListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/ChapterListAdapter.java index 22c15949a..cf0532cf1 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/ChapterListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/ChapterListAdapter.java @@ -138,9 +138,9 @@ public class ChapterListAdapter extends ArrayAdapter<Chapter> { if (current != null) { if (current == sc) { holder.title.setTextColor(convertView.getResources().getColor( - R.color.bright_blue)); + R.color.holo_blue_light)); holder.start.setTextColor(convertView.getResources().getColor( - R.color.bright_blue)); + R.color.holo_blue_light)); } else { holder.title.setTextColor(defaultTextColor); holder.start.setTextColor(defaultTextColor); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java index 445e4832c..efdf1a3c9 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java @@ -1,9 +1,9 @@ package de.danoeh.antennapod.adapter; -import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.support.v7.app.AlertDialog; import android.widget.Toast; import org.apache.commons.lang3.Validate; 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 062f883bc..3e4dd4deb 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java @@ -2,20 +2,20 @@ package de.danoeh.antennapod.adapter; 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; @@ -36,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; @@ -59,7 +58,10 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap private boolean locked; - private int position = -1; + private FeedItem selectedItem; + + private final int playingBackGroundColor; + private final int normalBackGroundColor; public QueueRecyclerAdapter(MainActivity mainActivity, ItemAccess itemAccess, @@ -72,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) { @@ -88,17 +97,18 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap FeedItem item = itemAccess.getItem(pos); holder.bind(item); holder.itemView.setOnLongClickListener(v -> { - position = pos; + selectedItem = item; return false; }); } - public int getItemCount() { - return itemAccess.getCount(); + @Nullable + public FeedItem getSelectedItem() { + return selectedItem; } - public int getPosition() { - return position; + public int getItemCount() { + return itemAccess.getCount(); } public class ViewHolder extends RecyclerView.ViewHolder @@ -106,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; @@ -120,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); @@ -247,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); @@ -262,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 3656c3638..3940eb8b6 100644 --- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java +++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java @@ -1,13 +1,13 @@ package de.danoeh.antennapod.asynctask; import android.annotation.SuppressLint; -import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.AsyncTask; +import android.support.v7.app.AlertDialog; import android.util.Log; import java.io.File; diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java index 5486bc4fb..86636485d 100644 --- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java +++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java @@ -1,12 +1,12 @@ package de.danoeh.antennapod.asynctask; import android.annotation.SuppressLint; -import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.os.AsyncTask; +import android.support.v7.app.AlertDialog; import android.util.Log; import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.R; @@ -37,8 +37,7 @@ public class OpmlImportWorker extends @Override protected ArrayList<OpmlElement> doInBackground(Void... params) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Starting background work"); + Log.d(TAG, "Starting background work"); if (mReader==null) { return null; @@ -72,21 +71,14 @@ public class OpmlImportWorker extends } progDialog.dismiss(); if (exception != null) { - if (BuildConfig.DEBUG) - Log.d(TAG, - "An error occurred while trying to parse the opml document"); + Log.d(TAG, "An error occurred while trying to parse the opml document"); AlertDialog.Builder alert = new AlertDialog.Builder(context); alert.setTitle(R.string.error_label); alert.setMessage(context.getString(R.string.opml_reader_error) + exception.getMessage()); - alert.setNeutralButton(android.R.string.ok, new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - - }); + alert.setNeutralButton(android.R.string.ok, (dialog, which) -> { + dialog.dismiss(); + }); alert.create().show(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java index 1585f9b86..75b1bc8d2 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java @@ -2,9 +2,9 @@ package de.danoeh.antennapod.dialog; import android.annotation.SuppressLint; import android.app.Activity; -import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.support.v7.app.AlertDialog; import android.view.View; import android.widget.CheckBox; import android.widget.SeekBar; diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java index 16fb77f2a..5f531e88f 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java @@ -1,8 +1,8 @@ package de.danoeh.antennapod.dialog; -import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.support.v7.app.AlertDialog; import android.text.Editable; import android.text.InputType; import android.view.View; @@ -26,28 +26,19 @@ public class GpodnetSetHostnameDialog { et.setInputType(InputType.TYPE_TEXT_VARIATION_URI); dialog.setTitle(R.string.pref_gpodnet_sethostname_title) .setView(setupContentView(context, et)) - .setPositiveButton(R.string.confirm_label, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - final Editable e = et.getText(); - if (e != null) { - GpodnetPreferences.setHostname(e.toString()); - } - dialog.dismiss(); + .setPositiveButton(R.string.confirm_label, (dialog1, which) -> { + final Editable e = et.getText(); + if (e != null) { + GpodnetPreferences.setHostname(e.toString()); } + dialog1.dismiss(); }) - .setNegativeButton(R.string.cancel_label, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.cancel(); - } + .setNegativeButton(R.string.cancel_label, (dialog1, which) -> { + dialog1.cancel(); }) - .setNeutralButton(R.string.pref_gpodnet_sethostname_use_default_host, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - GpodnetPreferences.setHostname(GpodnetService.DEFAULT_BASE_HOST); - dialog.dismiss(); - } + .setNeutralButton(R.string.pref_gpodnet_sethostname_use_default_host, (dialog1, which) -> { + GpodnetPreferences.setHostname(GpodnetService.DEFAULT_BASE_HOST); + dialog1.dismiss(); }) .setCancelable(true); return dialog.show(); diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java index a699706a8..930079e40 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java @@ -17,11 +17,14 @@ import android.widget.EditText; import android.widget.Spinner; import android.widget.Toast; +import com.afollestad.materialdialogs.DialogAction; +import com.afollestad.materialdialogs.MaterialDialog; + import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.R; -public abstract class SleepTimerDialog extends Dialog { +public abstract class SleepTimerDialog { private static final String TAG = SleepTimerDialog.class.getSimpleName(); @@ -35,39 +38,54 @@ public abstract class SleepTimerDialog extends Dialog { private String PREF_SHAKE_TO_RESET = "ShakeToReset"; private SharedPreferences prefs; + private MaterialDialog dialog; private EditText etxtTime; private Spinner spTimeUnit; private CheckBox cbShakeToReset; private CheckBox cbVibrate; - private Button butConfirm; - private Button butCancel; + private TimeUnit[] units = { TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS }; - public SleepTimerDialog(Context context, int titleTextId, int leftButtonTextId) { - super(context); + public SleepTimerDialog(Context context) { this.context = context; prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - requestWindowFeature(Window.FEATURE_NO_TITLE); - String[] spinnerContent = new String[] { - context.getString(R.string.time_seconds), - context.getString(R.string.time_minutes), - context.getString(R.string.time_hours) }; - - setContentView(R.layout.time_dialog); - etxtTime = (EditText) findViewById(R.id.etxtTime); - spTimeUnit = (Spinner) findViewById(R.id.spTimeUnit); - cbShakeToReset = (CheckBox) findViewById(R.id.cbShakeToReset); - cbVibrate = (CheckBox) findViewById(R.id.cbVibrate); - butConfirm = (Button) findViewById(R.id.butConfirm); - butCancel = (Button) findViewById(R.id.butCancel); + public MaterialDialog createNewDialog() { + MaterialDialog.Builder builder = new MaterialDialog.Builder(context); + builder.title(R.string.set_sleeptimer_label); + builder.customView(R.layout.time_dialog, false); + builder.positiveText(R.string.set_sleeptimer_label); + builder.negativeText(R.string.cancel_label); + builder.callback(new MaterialDialog.ButtonCallback() { + @Override + public void onNegative(MaterialDialog dialog) { + dialog.dismiss(); + } - setTitle(R.string.set_sleeptimer_label); + @Override + public void onPositive(MaterialDialog dialog) { + try { + savePreferences(); + long input = readTimeMillis(); + onTimerSet(input, cbShakeToReset.isChecked(), cbVibrate.isChecked()); + dialog.dismiss(); + } catch (NumberFormatException e) { + e.printStackTrace(); + Toast toast = Toast.makeText(context, R.string.time_dialog_invalid_input, + Toast.LENGTH_LONG); + toast.show(); + } + } + }); + dialog = builder.build(); + + View view = dialog.getView(); + etxtTime = (EditText) view.findViewById(R.id.etxtTime); + spTimeUnit = (Spinner) view.findViewById(R.id.spTimeUnit); + cbShakeToReset = (CheckBox) view.findViewById(R.id.cbShakeToReset); + cbVibrate = (CheckBox) view.findViewById(R.id.cbVibrate); etxtTime.setText(prefs.getString(PREF_VALUE, "15")); etxtTime.addTextChangedListener(new TextWatcher() { @@ -84,15 +102,16 @@ public abstract class SleepTimerDialog extends Dialog { public void onTextChanged(CharSequence s, int start, int before, int count) { } }); - etxtTime.postDelayed(new Runnable() { - @Override - public void run() { - InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(etxtTime, InputMethodManager.SHOW_IMPLICIT); - } + etxtTime.postDelayed(() -> { + InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(etxtTime, InputMethodManager.SHOW_IMPLICIT); }, 100); - ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(this.getContext(), + String[] spinnerContent = new String[] { + context.getString(R.string.time_seconds), + context.getString(R.string.time_minutes), + context.getString(R.string.time_hours) }; + ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, spinnerContent); spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spTimeUnit.setAdapter(spinnerAdapter); @@ -102,40 +121,16 @@ public abstract class SleepTimerDialog extends Dialog { cbShakeToReset.setChecked(prefs.getBoolean(PREF_SHAKE_TO_RESET, true)); cbVibrate.setChecked(prefs.getBoolean(PREF_VIBRATE, true)); - butConfirm.setText(R.string.set_sleeptimer_label); - butConfirm.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - try { - savePreferences(); - long input = readTimeMillis(); - onTimerSet(input, cbShakeToReset.isChecked(), cbVibrate.isChecked()); - dismiss(); - } catch (NumberFormatException e) { - e.printStackTrace(); - Toast toast = Toast.makeText(context, R.string.time_dialog_invalid_input, - Toast.LENGTH_LONG); - toast.show(); - } - } - }); - - butCancel.setText(R.string.cancel_label); - butCancel.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - dismiss(); - } - }); + return dialog; } private void checkInputLength(int length) { if (length > 0) { Log.d(TAG, "Length is larger than 0, enabling confirm button"); - butConfirm.setEnabled(true); + dialog.getActionButton(DialogAction.POSITIVE).setEnabled(true); } else { Log.d(TAG, "Length is smaller than 0, disabling confirm button"); - butConfirm.setEnabled(false); + dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false); } } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java index 5f6e3d0e2..4b512a48d 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java @@ -1,11 +1,11 @@ package de.danoeh.antennapod.dialog; -import android.app.AlertDialog; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Build; +import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.View; 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 3c3f7f01c..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; - Collections.swap(queue, from, to); - 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 @@ -327,20 +323,33 @@ public class QueueFragment extends Fragment { if(!isVisible()) { return false; } - int pos = recyclerAdapter.getPosition(); - FeedItem selectedItem = itemAccess.getItem(pos); - + FeedItem selectedItem = recyclerAdapter.getSelectedItem(); if (selectedItem == null) { - Log.i(TAG, "Selected item at position " + pos + " was null, ignoring selection"); + Log.i(TAG, "Selected item was null, ignoring selection"); 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,9 +376,9 @@ public class QueueFragment extends Fragment { int from = viewHolder.getAdapterPosition(); int to = target.getAdapterPosition(); Log.d(TAG, "move(" + from + ", " + to + ")"); - Collections.swap(queue, from, to); + queue.add(to, queue.remove(from)); recyclerAdapter.notifyItemMoved(from, to); - DBWriter.moveQueueItem(from, to, false); + DBWriter.moveQueueItem(from, to, true); return true; } @@ -447,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); @@ -482,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() { @@ -500,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 @@ -553,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(); @@ -562,6 +563,7 @@ public class QueueFragment extends Fragment { }; private void loadItems() { + Log.d(TAG, "loadItems()"); if(subscription != null) { subscription.unsubscribe(); } @@ -570,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/menuhandler/FeedMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java index f32a1c2ee..84da32a40 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java @@ -1,10 +1,10 @@ package de.danoeh.antennapod.menuhandler; -import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; +import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/CustomEditTextPreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/CustomEditTextPreference.java deleted file mode 100644 index 898a56004..000000000 --- a/app/src/main/java/de/danoeh/antennapod/preferences/CustomEditTextPreference.java +++ /dev/null @@ -1,33 +0,0 @@ -package de.danoeh.antennapod.preferences; - -import android.app.AlertDialog; -import android.content.Context; -import android.os.Build; -import android.preference.EditTextPreference; -import android.util.AttributeSet; - -import de.danoeh.antennapod.R; - -public class CustomEditTextPreference extends EditTextPreference { - - public CustomEditTextPreference(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public CustomEditTextPreference(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public CustomEditTextPreference(Context context) { - super(context); - } - - @Override - protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { - if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { - builder.setInverseBackgroundForced(true); - getEditText().setTextColor(getContext().getResources().getColor(R.color.black)); - } - } - -} 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 138246038..73d7da0f2 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -1,7 +1,7 @@ package de.danoeh.antennapod.preferences; +import android.annotation.SuppressLint; import android.app.Activity; -import android.app.AlertDialog; import android.app.TimePickerDialog; import android.content.Context; import android.content.DialogInterface; @@ -17,7 +17,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 +34,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import de.danoeh.antennapod.BuildConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.AboutActivity; import de.danoeh.antennapod.activity.DirectoryChooserActivity; @@ -41,6 +43,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 +54,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 +164,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() { @@ -394,16 +401,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); @@ -564,9 +592,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 +675,47 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc builder.create().show(); } + private void showChooseDataFolderDialog() { + Context context = ui.getActivity(); + String dataFolder = UserPreferences.getDataFolder(context, 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(); |