summaryrefslogtreecommitdiff
path: root/app/src/main/java/de/danoeh/antennapod
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod')
-rw-r--r--app/src/main/java/de/danoeh/antennapod/PodcastApp.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/UpdateManager.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java644
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java104
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java593
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java199
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ChapterListAdapter.java199
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java198
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java16
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java51
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java34
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java201
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java29
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java77
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java82
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java48
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java192
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java45
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java21
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java247
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java15
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java29
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java27
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java8
29 files changed, 1697 insertions, 1403 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
index c1d4bc4fd..829a49a15 100644
--- a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
+++ b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
@@ -57,8 +57,8 @@ public class PodcastApp extends Application {
singleton = this;
PodDBAdapter.init(this);
- UpdateManager.init(this);
UserPreferences.init(this);
+ UpdateManager.init(this);
PlaybackPreferences.init(this);
NetworkUtils.init(this);
EventDistributor.getInstance();
diff --git a/app/src/main/java/de/danoeh/antennapod/UpdateManager.java b/app/src/main/java/de/danoeh/antennapod/UpdateManager.java
index b1d7fffc8..0b3c43381 100644
--- a/app/src/main/java/de/danoeh/antennapod/UpdateManager.java
+++ b/app/src/main/java/de/danoeh/antennapod/UpdateManager.java
@@ -5,14 +5,18 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.os.Build;
import android.util.Log;
+import org.antennapod.audio.MediaPlayer;
+
import java.io.File;
import java.util.List;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
@@ -83,6 +87,11 @@ public class UpdateManager {
}
}.start();
}
+ if(oldVersionCode < 1050004) {
+ if(MediaPlayer.isPrestoLibraryInstalled(context) && Build.VERSION.SDK_INT >= 16) {
+ UserPreferences.enableSonic(true);
+ }
+ }
}
}
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 835ac29cd..12bae2f51 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
@@ -1,54 +1,44 @@
package de.danoeh.antennapod.activity;
+import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
-import android.content.res.TypedArray;
-import android.graphics.drawable.BitmapDrawable;
-import android.os.Bundle;
+import android.os.Build;
+import android.support.annotation.Nullable;
+import android.support.design.widget.AppBarLayout;
import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v4.app.ListFragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentStatePagerAdapter;
+import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
+import android.util.TypedValue;
import android.view.ContextMenu;
-import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.LinearInterpolator;
-import android.view.animation.ScaleAnimation;
import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.ImageButton;
import android.widget.ListView;
-import android.widget.PopupWindow;
-import android.widget.SeekBar;
-import android.widget.TextView;
-import com.bumptech.glide.Glide;
+import com.viewpagerindicator.CirclePageIndicator;
-import org.apache.commons.lang3.ArrayUtils;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.adapter.ChapterListAdapter;
+import de.danoeh.antennapod.adapter.ChaptersListAdapter;
import de.danoeh.antennapod.adapter.NavListAdapter;
import de.danoeh.antennapod.core.asynctask.FeedRemover;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
-import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
-import de.danoeh.antennapod.core.feed.SimpleChapter;
-import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
@@ -57,8 +47,14 @@ import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
+import de.danoeh.antennapod.fragment.AddFeedFragment;
+import de.danoeh.antennapod.fragment.ChaptersFragment;
import de.danoeh.antennapod.fragment.CoverFragment;
+import de.danoeh.antennapod.fragment.DownloadsFragment;
+import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.ItemDescriptionFragment;
+import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
+import de.danoeh.antennapod.fragment.QueueFragment;
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
import de.danoeh.antennapod.preferences.PreferenceController;
import rx.Observable;
@@ -69,85 +65,40 @@ import rx.schedulers.Schedulers;
/**
* Activity for playing audio files.
*/
-public class AudioplayerActivity extends MediaplayerActivity implements ItemDescriptionFragment.ItemDescriptionFragmentCallback,
- NavDrawerActivity {
+public class AudioplayerActivity extends MediaplayerActivity implements NavDrawerActivity {
private static final int POS_COVER = 0;
private static final int POS_DESCR = 1;
private static final int POS_CHAPTERS = 2;
private static final int NUM_CONTENT_FRAGMENTS = 3;
- private static final int POS_NONE = -1;
final String TAG = "AudioplayerActivity";
private static final String PREFS = "AudioPlayerActivityPreferences";
private static final String PREF_KEY_SELECTED_FRAGMENT_POSITION = "selectedFragmentPosition";
- private static final String PREF_PLAYABLE_ID = "playableId";
+
+ public static final String[] NAV_DRAWER_TAGS = {
+ QueueFragment.TAG,
+ EpisodesFragment.TAG,
+ DownloadsFragment.TAG,
+ PlaybackHistoryFragment.TAG,
+ AddFeedFragment.TAG
+ };
+
+ private AtomicBoolean isSetup = new AtomicBoolean(false);
private DrawerLayout drawerLayout;
private NavListAdapter navAdapter;
private ListView navList;
- private AdapterView.AdapterContextMenuInfo lastMenuInfo = null;
private View navDrawer;
private ActionBarDrawerToggle drawerToggle;
+ private int mPosition = -1;
- private Fragment[] detachedFragments;
-
- private CoverFragment coverFragment;
- private ItemDescriptionFragment descriptionFragment;
- private ListFragment chapterFragment;
-
- private Fragment currentlyShownFragment;
- private int currentlyShownPosition = -1;
- private int lastShownPosition = POS_NONE;
- /**
- * Used if onResume was called without loadMediaInfo.
- */
- private int savedPosition = -1;
-
- private TextView txtvTitle;
- private Button butPlaybackSpeed;
- private ImageButton butNavChaptersShownotes;
- private ImageButton butShowCover;
+ private Playable media;
+ private ViewPager mPager;
+ private AudioplayerPagerAdapter mPagerAdapter;
private Subscription subscription;
- private PopupWindow popupWindow;
-
- private void resetFragmentView() {
- FragmentTransaction fT = getSupportFragmentManager().beginTransaction();
-
- if (coverFragment != null) {
- Log.d(TAG, "Removing cover fragment");
- fT.remove(coverFragment);
- }
- if (descriptionFragment != null) {
- Log.d(TAG, "Removing description fragment");
- fT.remove(descriptionFragment);
- }
- if (chapterFragment != null) {
- Log.d(TAG, "Removing chapter fragment");
- fT.remove(chapterFragment);
- }
- if (currentlyShownFragment != null) {
- Log.d(TAG, "Removing currently shown fragment");
- fT.remove(currentlyShownFragment);
- }
- for (int i = 0; i < detachedFragments.length; i++) {
- Fragment f = detachedFragments[i];
- if (f != null) {
- Log.d(TAG, "Removing detached fragment");
- fT.remove(f);
- }
- }
- fT.commit();
- currentlyShownFragment = null;
- coverFragment = null;
- descriptionFragment = null;
- chapterFragment = null;
- currentlyShownPosition = -1;
- detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS];
- }
-
@Override
protected void onStop() {
super.onStop();
@@ -156,36 +107,33 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
subscription.unsubscribe();
}
EventDistributor.getInstance().unregister(contentUpdate);
+ saveCurrentFragment();
}
@Override
- protected void chooseTheme() {
- setTheme(UserPreferences.getNoTitleTheme());
+ public void onDestroy() {
+ super.onDestroy();
+ // don't risk creating memory leaks
+ navAdapter = null;
+ drawerToggle = null;
+ mPager = null;
+ mPagerAdapter = null;
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS];
+ protected void chooseTheme() {
+ setTheme(UserPreferences.getNoTitleTheme());
}
- private void savePreferences() {
+ private void saveCurrentFragment() {
+ if(mPager == null) {
+ return;
+ }
Log.d(TAG, "Saving preferences");
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
- if (currentlyShownPosition >= 0 && controller != null
- && controller.getMedia() != null) {
- editor.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION,
- currentlyShownPosition);
- editor.putString(PREF_PLAYABLE_ID, controller.getMedia()
- .getIdentifier().toString());
- } else {
- editor.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, -1);
- editor.putString(PREF_PLAYABLE_ID, "");
- }
- editor.commit();
-
- savedPosition = currentlyShownPosition;
+ prefs.edit()
+ .putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, mPager.getCurrentItem())
+ .commit();
}
@Override
@@ -194,53 +142,11 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
drawerToggle.onConfigurationChanged(newConfig);
}
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- // super.onSaveInstanceState(outState); would cause crash
- Log.d(TAG, "onSaveInstanceState");
- }
-
- @Override
- protected void onPause() {
- savePreferences();
- resetFragmentView();
- super.onPause();
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- restoreFromPreferences();
- }
-
- /**
- * Tries to restore the selected fragment position from the Activity's
- * preferences.
- *
- * @return true if restoreFromPrefernces changed the activity's state
- */
- private boolean restoreFromPreferences() {
+ private void loadLastFragment() {
Log.d(TAG, "Restoring instance state");
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
- int savedPosition = prefs.getInt(PREF_KEY_SELECTED_FRAGMENT_POSITION,
- -1);
- String playableId = prefs.getString(PREF_PLAYABLE_ID, "");
-
- if (savedPosition != -1
- && controller != null
- && controller.getMedia() != null
- && controller.getMedia().getIdentifier().toString()
- .equals(playableId)) {
- switchToFragment(savedPosition);
- return true;
- } else if (controller == null || controller.getMedia() == null) {
- Log.d(TAG, "Couldn't restore from preferences: controller or media was null");
- } else {
- Log.d(TAG, "Couldn't restore from preferences: savedPosition was -1 or saved identifier and playable identifier didn't match.\nsavedPosition: "
- + savedPosition + ", id: " + playableId);
-
- }
- return false;
+ int lastPosition = prefs.getInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, -1);
+ mPager.setCurrentItem(lastPosition);
}
@Override
@@ -260,8 +166,9 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
true);
startService(launchIntent);
}
- if (savedPosition != -1) {
- switchToFragment(savedPosition);
+ if(mPagerAdapter != null && controller != null && controller.getMedia() != media) {
+ media = controller.getMedia();
+ mPagerAdapter.onMediaChanged(media);
}
EventDistributor.getInstance().register(contentUpdate);
@@ -292,147 +199,28 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
@Override
protected void clearStatusMsg() {
// TODO Hide progress bar here
-
}
- /**
- * Changes the currently displayed fragment.
- *
- * @param pos Must be POS_COVER, POS_DESCR, or POS_CHAPTERS
- */
- private void switchToFragment(int pos) {
- Log.d(TAG, "Switching contentView to position " + pos);
- if (currentlyShownPosition != pos && controller != null) {
- Playable media = controller.getMedia();
- if (media != null) {
- FragmentTransaction ft = getSupportFragmentManager()
- .beginTransaction();
- if (currentlyShownFragment != null) {
- detachedFragments[currentlyShownPosition] = currentlyShownFragment;
- ft.detach(currentlyShownFragment);
- }
- switch (pos) {
- case POS_COVER:
- if (coverFragment == null) {
- Log.i(TAG, "Using new coverfragment");
- coverFragment = CoverFragment.newInstance(media);
- }
- currentlyShownFragment = coverFragment;
- break;
- case POS_DESCR:
- if (descriptionFragment == null) {
- descriptionFragment = ItemDescriptionFragment
- .newInstance(media, true, true);
- }
- currentlyShownFragment = descriptionFragment;
- break;
- case POS_CHAPTERS:
- if (chapterFragment == null) {
- chapterFragment = new 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);
- }
- };
- chapterFragment.setListAdapter(new ChapterListAdapter(
- AudioplayerActivity.this, 0, media
- .getChapters(), media, position -> {
- Chapter chapter = (Chapter)
- chapterFragment.getListAdapter().getItem(position);
- controller.seekToChapter(chapter);
- }
- ));
- }
- currentlyShownFragment = chapterFragment;
- break;
- }
- if (currentlyShownFragment != null) {
- lastShownPosition = currentlyShownPosition;
- currentlyShownPosition = pos;
- if (detachedFragments[pos] != null) {
- Log.d(TAG, "Reattaching fragment at position " + pos);
- ft.attach(detachedFragments[pos]);
- } else {
- ft.add(R.id.contentView, currentlyShownFragment);
- }
- ft.disallowAddToBackStack();
- ft.commit();
- updateNavButtonDrawable();
- }
- }
- }
- }
-
- /**
- * Switches to the fragment that was displayed before the current one or the description fragment
- * if no fragment was previously displayed.
- */
- public void switchToLastFragment() {
- if (lastShownPosition != POS_NONE) {
- switchToFragment(lastShownPosition);
- } else {
- switchToFragment(POS_DESCR);
- }
- }
-
- private void updateNavButtonDrawable() {
-
- final int[] buttonTexts = new int[]{R.string.show_shownotes_label,
- R.string.show_chapters_label};
-
- final TypedArray drawables = obtainStyledAttributes(new int[]{
- R.attr.navigation_shownotes, R.attr.navigation_chapters});
- final Playable media = controller.getMedia();
- if (butNavChaptersShownotes != null && butShowCover != null && media != null) {
-
- butNavChaptersShownotes.setTag(R.id.imageloader_key, null);
- setNavButtonVisibility();
- switch (currentlyShownPosition) {
- case POS_COVER:
- butShowCover.setVisibility(View.GONE);
- if (lastShownPosition == POS_CHAPTERS) {
- butNavChaptersShownotes.setImageDrawable(drawables.getDrawable(1));
- butNavChaptersShownotes.setContentDescription(getString(buttonTexts[1]));
- } else {
- butNavChaptersShownotes.setImageDrawable(drawables.getDrawable(0));
- butNavChaptersShownotes.setContentDescription(getString(buttonTexts[0]));
- }
- break;
- case POS_DESCR:
- butShowCover.setVisibility(View.VISIBLE);
- butNavChaptersShownotes.setImageDrawable(drawables.getDrawable(1));
- butNavChaptersShownotes.setContentDescription(getString(buttonTexts[1]));
- break;
- case POS_CHAPTERS:
- butShowCover.setVisibility(View.VISIBLE);
- butNavChaptersShownotes.setImageDrawable(drawables.getDrawable(0));
- butNavChaptersShownotes.setContentDescription(getString(buttonTexts[0]));
- break;
- }
- }
- drawables.recycle();
- }
@Override
protected void setupGUI() {
+ if(isSetup.getAndSet(true)) {
+ return;
+ }
super.setupGUI();
- resetFragmentView();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setTitle("");
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ findViewById(R.id.shadow).setVisibility(View.GONE);
+ AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appBar);
+ float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics());
+ appBarLayout.setElevation(px);
+ }
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
navList = (ListView) findViewById(R.id.nav_list);
navDrawer = findViewById(R.id.nav_layout);
- butPlaybackSpeed = (Button) findViewById(R.id.butPlaybackSpeed);
- butNavChaptersShownotes = (ImageButton) findViewById(R.id.butNavChaptersShownotes);
- butShowCover = (ImageButton) findViewById(R.id.butCover);
- txtvTitle = (TextView) findViewById(R.id.txtvTitle);
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close);
drawerToggle.setDrawerIndicatorEnabled(false);
@@ -450,6 +238,15 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
}
drawerLayout.closeDrawer(navDrawer);
});
+ navList.setOnItemLongClickListener((parent, view, position, id) -> {
+ if (position < navAdapter.getTags().size()) {
+ showDrawerPreferencesDialog();
+ return true;
+ } else {
+ mPosition = position;
+ return false;
+ }
+ });
registerForContextMenu(navList);
drawerToggle.syncState();
@@ -458,128 +255,13 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
startActivity(new Intent(AudioplayerActivity.this, PreferenceController.getPreferenceActivity()));
});
- butNavChaptersShownotes.setOnClickListener(v -> {
- if (currentlyShownPosition == POS_CHAPTERS) {
- switchToFragment(POS_DESCR);
- } else if (currentlyShownPosition == POS_DESCR) {
- switchToFragment(POS_CHAPTERS);
- } else if (currentlyShownPosition == POS_COVER) {
- switchToLastFragment();
- }
- });
-
- butShowCover.setOnClickListener(v -> switchToFragment(POS_COVER));
-
- butPlaybackSpeed.setOnClickListener(v -> {
- if (controller != null && controller.canSetPlaybackSpeed()) {
- String[] availableSpeeds = UserPreferences
- .getPlaybackSpeedArray();
- String currentSpeed = UserPreferences.getPlaybackSpeed();
-
- // Provide initial value in case the speed list has changed
- // out from under us
- // and our current speed isn't in the new list
- String newSpeed;
- if (availableSpeeds.length > 0) {
- newSpeed = availableSpeeds[0];
- } else {
- newSpeed = "1.0";
- }
-
- for (int i = 0; i < availableSpeeds.length; i++) {
- if (availableSpeeds[i].equals(currentSpeed)) {
- if (i == availableSpeeds.length - 1) {
- newSpeed = availableSpeeds[0];
- } else {
- newSpeed = availableSpeeds[i + 1];
- }
- break;
- }
- }
- UserPreferences.setPlaybackSpeed(newSpeed);
- controller.setPlaybackSpeed(Float.parseFloat(newSpeed));
- }
- });
-
- butPlaybackSpeed.setOnLongClickListener(v -> {
-
- String[] availableSpeeds = getResources().getStringArray(R.array.playback_speed_values);
- String currentSpeed = UserPreferences.getPlaybackSpeed();
-
- LayoutInflater inflater = getLayoutInflater();
- View popupView = inflater.inflate(R.layout.choose_speed_dialog, null);
- TextView txtvSelectedSpeed = (TextView) popupView.findViewById(R.id.txtvSelectedSpeed);
- SeekBar sbSelectSpeed = (SeekBar) popupView.findViewById(R.id.sbSelectSpeed);
-
- txtvSelectedSpeed.setText(currentSpeed);
- int progress = ArrayUtils.indexOf(availableSpeeds, currentSpeed);
- int max = Math.max(progress, ArrayUtils.indexOf(availableSpeeds, "2.50"));
- sbSelectSpeed.setMax(max);
- sbSelectSpeed.setProgress(progress);
- sbSelectSpeed.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- txtvSelectedSpeed.setText(availableSpeeds[progress]);
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- String selectedSpeed = availableSpeeds[sbSelectSpeed.getProgress()];
- UserPreferences.setPlaybackSpeed(selectedSpeed);
- controller.setPlaybackSpeed(Float.parseFloat(selectedSpeed));
- if (popupWindow != null && popupWindow.isShowing()) {
- popupWindow.dismiss();
- }
- ScaleAnimation anim = new ScaleAnimation(1.0f, 1.33f, 1.0f, 1.33f,
- butPlaybackSpeed.getWidth()/2, butPlaybackSpeed.getHeight()/2);
- anim.setDuration(150);
- anim.setRepeatMode(ScaleAnimation.REVERSE);
- anim.setRepeatCount(1);
- anim.setInterpolator(new LinearInterpolator());
- butPlaybackSpeed.startAnimation(anim);
- }
- });
- popupWindow = new PopupWindow(popupView,
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT,
- true);
- popupWindow.setBackgroundDrawable(new BitmapDrawable());
- popupWindow.setOutsideTouchable(true);
- popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);
- return true;
- });
- }
-
- private void setNavButtonVisibility() {
- if (butNavChaptersShownotes != null) {
- if (controller != null) {
- Playable media = controller.getMedia();
- if (media != null) {
- if (media.getChapters() != null || currentlyShownPosition == POS_COVER) {
- butNavChaptersShownotes.setVisibility(View.VISIBLE);
- return;
- }
- }
- }
- butNavChaptersShownotes.setVisibility(View.GONE);
- }
-
- }
-
- @Override
- protected void onPlaybackSpeedChange() {
- super.onPlaybackSpeedChange();
- updateButPlaybackSpeed();
- }
-
- private void updateButPlaybackSpeed() {
- if (controller != null && controller.canSetPlaybackSpeed()) {
- butPlaybackSpeed.setText(UserPreferences.getPlaybackSpeed());
- }
+ mPager = (ViewPager) findViewById(R.id.pager);
+ mPagerAdapter = new AudioplayerPagerAdapter(getSupportFragmentManager());
+ mPager.setAdapter(mPagerAdapter);
+ CirclePageIndicator pageIndicator = (CirclePageIndicator) findViewById(R.id.page_indicator);
+ pageIndicator.setViewPager(mPager);
+ loadLastFragment();
+ mPager.onSaveInstanceState();
}
@Override
@@ -593,49 +275,20 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
if (!super.loadMediaInfo()) {
return false;
}
- final Playable media = controller.getMedia();
- if (media == null) {
- return false;
- }
- txtvTitle.setText(media.getEpisodeTitle());
- getSupportActionBar().setTitle("");
- Glide.with(this)
- .load(media.getImageUri())
- .placeholder(R.color.light_gray)
- .error(R.color.light_gray)
- .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
- .fitCenter()
- .dontAnimate()
- .into(butShowCover);
-
- setNavButtonVisibility();
-
- if (currentlyShownPosition == -1) {
- if (!restoreFromPreferences()) {
- switchToFragment(POS_COVER);
- }
- }
- if (currentlyShownFragment instanceof AudioplayerContentFragment) {
- ((AudioplayerContentFragment) currentlyShownFragment)
- .onDataSetChanged(media);
+ if(controller.getMedia() != media) {
+ media = controller.getMedia();
+ mPagerAdapter.onMediaChanged(media);
}
-
- if (controller == null
- || !controller.canSetPlaybackSpeed()) {
- butPlaybackSpeed.setVisibility(View.GONE);
- } else {
- butPlaybackSpeed.setVisibility(View.VISIBLE);
- }
-
- updateButPlaybackSpeed();
return true;
}
public void notifyMediaPositionChanged() {
- if (chapterFragment != null) {
- ArrayAdapter<SimpleChapter> adapter = (ArrayAdapter<SimpleChapter>) chapterFragment
- .getListAdapter();
- adapter.notifyDataSetChanged();
+ ChaptersFragment chaptersFragment = mPagerAdapter.getChaptersFragment();
+ if(chaptersFragment != null) {
+ ChaptersListAdapter adapter = (ChaptersListAdapter) chaptersFragment.getListAdapter();
+ if (adapter != null) {
+ adapter.notifyDataSetChanged();
+ }
}
}
@@ -659,7 +312,6 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
clearStatusMsg();
}
- @Override
public PlaybackController getPlaybackController() {
return controller;
}
@@ -669,10 +321,6 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
return drawerLayout != null && navDrawer != null && drawerLayout.isDrawerOpen(navDrawer);
}
- public interface AudioplayerContentFragment {
- void onDataSetChanged(Playable media);
- }
-
@Override
protected int getContentViewResourceId() {
return R.layout.audioplayer_activity;
@@ -704,24 +352,15 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
menu.setHeaderTitle(feed.getTitle());
// episodes are not loaded, so we cannot check if the podcast has new or unplayed ones!
-
- // we may need to reference this elsewhere...
- lastMenuInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
}
@Override
public boolean onContextItemSelected(MenuItem item) {
- AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
-
- if(menuInfo == null) {
- menuInfo = lastMenuInfo;
- }
-
- if(menuInfo.targetView.getParent() instanceof ListView == false
- || ((ListView)menuInfo.targetView.getParent()).getId() != R.id.nav_list) {
+ final int position = mPosition;
+ mPosition = -1; // reset
+ if(position < 0) {
return false;
}
- int position = menuInfo.position;
Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
switch(item.getItemId()) {
case R.id.mark_all_seen_item:
@@ -772,11 +411,43 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
public void onBackPressed() {
if(isDrawerOpen()) {
drawerLayout.closeDrawer(navDrawer);
- } else {
+ } else if (mPager.getCurrentItem() == 0) {
+ // If the user is currently looking at the first step, allow the system to handle the
+ // Back button. This calls finish() on this activity and pops the back stack.
super.onBackPressed();
+ } else {
+ // Otherwise, select the previous step.
+ mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
}
+ public void showDrawerPreferencesDialog() {
+ final List<String> hiddenDrawerItems = UserPreferences.getHiddenDrawerItems();
+ String[] navLabels = new String[NAV_DRAWER_TAGS.length];
+ final boolean[] checked = new boolean[NAV_DRAWER_TAGS.length];
+ for (int i = 0; i < NAV_DRAWER_TAGS.length; i++) {
+ String tag = NAV_DRAWER_TAGS[i];
+ navLabels[i] = navAdapter.getLabel(tag);
+ if (!hiddenDrawerItems.contains(tag)) {
+ checked[i] = true;
+ }
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.drawer_preferences);
+ builder.setMultiChoiceItems(navLabels, checked, (dialog, which, isChecked) -> {
+ if (isChecked) {
+ hiddenDrawerItems.remove(NAV_DRAWER_TAGS[which]);
+ } else {
+ hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]);
+ }
+ });
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
+ UserPreferences.setHiddenDrawerItems(hiddenDrawerItems);
+ });
+ builder.setNegativeButton(R.string.cancel_label, null);
+ builder.create().show();
+ }
private DBReader.NavDrawerData navDrawerData;
@@ -852,4 +523,65 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
}
};
+ public interface AudioplayerContentFragment {
+ void onMediaChanged(Playable media);
+ }
+
+ private class AudioplayerPagerAdapter extends FragmentStatePagerAdapter {
+
+ public AudioplayerPagerAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ private CoverFragment coverFragment;
+ private ItemDescriptionFragment itemDescriptionFragment;
+ private ChaptersFragment chaptersFragment;
+
+ public void onMediaChanged(Playable media) {
+ if(coverFragment != null) {
+ coverFragment.onMediaChanged(media);
+ }
+ if(itemDescriptionFragment != null) {
+ itemDescriptionFragment.onMediaChanged(media);
+ }
+ if(chaptersFragment != null) {
+ chaptersFragment.onMediaChanged(media);
+ }
+ }
+
+ @Nullable
+ public ChaptersFragment getChaptersFragment() {
+ return chaptersFragment;
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ Log.d(TAG, "getItem(" + position + ")");
+ switch (position) {
+ case POS_COVER:
+ if(coverFragment == null) {
+ coverFragment = CoverFragment.newInstance(media);
+ }
+ return coverFragment;
+ case POS_DESCR:
+ if(itemDescriptionFragment == null) {
+ itemDescriptionFragment = ItemDescriptionFragment.newInstance(media, true, true);
+ }
+ return itemDescriptionFragment;
+ case POS_CHAPTERS:
+ if(chaptersFragment == null) {
+ chaptersFragment = ChaptersFragment.newInstance(media, controller);
+ }
+ return chaptersFragment;
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return NUM_CONTENT_FRAGMENTS;
+ }
+ }
+
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java
index 80883e4ae..edb973a0c 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java
@@ -18,9 +18,9 @@ import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.CheckBox;
-import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
@@ -32,6 +32,7 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedFilter;
import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.UserPreferences;
@@ -61,8 +62,13 @@ public class FeedInfoActivity extends ActionBarActivity {
private TextView txtvUrl;
private EditText etxtUsername;
private EditText etxtPassword;
+ private EditText etxtFilterText;
+ private RadioButton rdoFilterInclude;
+ private RadioButton rdoFilterExclude;
private CheckBox cbxAutoDownload;
+ private CheckBox cbxKeepUpdated;
private Spinner spnAutoDelete;
+ private boolean filterInclude = true;
private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() {
@Override
@@ -100,9 +106,21 @@ public class FeedInfoActivity extends ActionBarActivity {
txtvAuthor = (TextView) findViewById(R.id.txtvAuthor);
txtvUrl = (TextView) findViewById(R.id.txtvUrl);
cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload);
+ cbxKeepUpdated = (CheckBox) findViewById(R.id.cbxKeepUpdated);
spnAutoDelete = (Spinner) findViewById(R.id.spnAutoDelete);
etxtUsername = (EditText) findViewById(R.id.etxtUsername);
etxtPassword = (EditText) findViewById(R.id.etxtPassword);
+ etxtFilterText = (EditText) findViewById(R.id.etxtEpisodeFilterText);
+ rdoFilterInclude = (RadioButton) findViewById(R.id.radio_filter_include);
+ rdoFilterInclude.setOnClickListener(v -> {
+ filterInclude = true;
+ filterTextChanged = true;
+ });
+ rdoFilterExclude = (RadioButton) findViewById(R.id.radio_filter_exclude);
+ rdoFilterExclude.setOnClickListener(v -> {
+ filterInclude = false;
+ filterTextChanged = true;
+ });
txtvUrl.setOnClickListener(copyUrlToClipboard);
@@ -151,15 +169,18 @@ public class FeedInfoActivity extends ActionBarActivity {
cbxAutoDownload.setEnabled(UserPreferences.isEnableAutodownload());
cbxAutoDownload.setChecked(prefs.getAutoDownload());
- cbxAutoDownload.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
- feed.getPreferences().setAutoDownload(checked);
- feed.savePreferences(FeedInfoActivity.this);
- ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(FeedInfoActivity.this,
- feed, checked);
- dialog.createNewDialog().show();
- }
+ cbxAutoDownload.setOnCheckedChangeListener((compoundButton, checked) -> {
+ feed.getPreferences().setAutoDownload(checked);
+ feed.savePreferences(FeedInfoActivity.this);
+ updateAutoDownloadSettings();
+ ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(FeedInfoActivity.this,
+ feed, checked);
+ dialog.createNewDialog().show();
+ });
+ cbxKeepUpdated.setChecked(prefs.getKeepUpdated());
+ cbxKeepUpdated.setOnCheckedChangeListener((compoundButton, checked) -> {
+ feed.getPreferences().setKeepUpdated(checked);
+ feed.savePreferences(FeedInfoActivity.this);
});
spnAutoDelete.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
@@ -184,6 +205,7 @@ public class FeedInfoActivity extends ActionBarActivity {
feed.getPreferences().setAutoDeleteAction(auto_delete_action);// p
autoDeleteChanged = true;
}
+
@Override
public void onNothingSelected(AdapterView<?> parent) {
// Another interface callback
@@ -197,8 +219,25 @@ public class FeedInfoActivity extends ActionBarActivity {
etxtUsername.addTextChangedListener(authTextWatcher);
etxtPassword.addTextChangedListener(authTextWatcher);
- supportInvalidateOptionsMenu();
+ FeedFilter filter = prefs.getFilter();
+ if (filter.includeOnly()) {
+ etxtFilterText.setText(filter.getIncludeFilter());
+ rdoFilterInclude.setChecked(true);
+ rdoFilterExclude.setChecked(false);
+ } else if (filter.excludeOnly()) {
+ etxtFilterText.setText(filter.getExcludeFilter());
+ rdoFilterInclude.setChecked(false);
+ rdoFilterExclude.setChecked(true);
+ } else {
+ Log.d(TAG, "No filter set");
+ rdoFilterInclude.setChecked(false);
+ rdoFilterExclude.setChecked(false);
+ etxtFilterText.setText("");
+ }
+ etxtFilterText.addTextChangedListener(filterTextWatcher);
+ supportInvalidateOptionsMenu();
+ updateAutoDownloadSettings();
} else {
Log.e(TAG, "Activity was started with invalid arguments");
}
@@ -227,6 +266,25 @@ public class FeedInfoActivity extends ActionBarActivity {
}
};
+ private boolean filterTextChanged = false;
+
+ private TextWatcher filterTextWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ filterTextChanged = true;
+ }
+ };
+
@Override
protected void onPause() {
super.onPause();
@@ -237,11 +295,24 @@ public class FeedInfoActivity extends ActionBarActivity {
prefs.setUsername(etxtUsername.getText().toString());
prefs.setPassword(etxtPassword.getText().toString());
}
- if (authInfoChanged || autoDeleteChanged) {
+ if (filterTextChanged) {
+ Log.d(TAG, "Filter info changed, saving...");
+ String filterText = etxtFilterText.getText().toString();
+ String includeString = "";
+ String excludeString = "";
+ if (filterInclude) {
+ includeString = filterText;
+ } else {
+ excludeString = filterText;
+ }
+ prefs.setFilter(new FeedFilter(includeString, excludeString));
+ }
+ if (authInfoChanged || autoDeleteChanged || filterTextChanged) {
DBWriter.setFeedPreferences(prefs);
}
authInfoChanged = false;
autoDeleteChanged = false;
+ filterTextChanged = false;
}
}
@@ -282,6 +353,15 @@ public class FeedInfoActivity extends ActionBarActivity {
}
}
+ private void updateAutoDownloadSettings() {
+ if (feed != null && feed.getPreferences() != null) {
+ boolean enabled = feed.getPreferences().getAutoDownload() && UserPreferences.isEnableAutodownload();
+ rdoFilterInclude.setEnabled(enabled);
+ rdoFilterExclude.setEnabled(enabled);
+ etxtFilterText.setEnabled(enabled);
+ }
+ }
+
private class ApplyToEpisodesDialog extends ConfirmationDialog {
private final Feed feed;
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
index 2181e7d2d..f96764b42 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
@@ -224,6 +224,9 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
if (prefs.getBoolean(PREF_IS_FIRST_LAUNCH, true)) {
new Handler().postDelayed(() -> drawerLayout.openDrawer(navDrawer), 1500);
+ // for backward compatibility, we only change defaults for fresh installs
+ UserPreferences.setUpdateInterval(12);
+
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean(PREF_IS_FIRST_LAUNCH, false);
edit.commit();
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 bfbf3d86f..bdc210651 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
@@ -1,34 +1,44 @@
package de.danoeh.antennapod.activity;
import android.annotation.TargetApi;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.res.TypedArray;
+import android.graphics.Color;
import android.graphics.PixelFormat;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v4.view.ViewCompat;
import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
+import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
import com.bumptech.glide.Glide;
+import com.joanzapata.iconify.IconDrawable;
+import com.joanzapata.iconify.fonts.FontAwesomeIcons;
import de.danoeh.antennapod.R;
+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;
+import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
+import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.StorageUtils;
@@ -36,13 +46,17 @@ import de.danoeh.antennapod.core.util.playback.MediaPlayerError;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.dialog.SleepTimerDialog;
+import de.danoeh.antennapod.dialog.VariableSpeedDialog;
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
+
/**
* Provides general features which are both needed for playing audio and video
* files.
*/
-public abstract class MediaplayerActivity extends ActionBarActivity
- implements OnSeekBarChangeListener {
+public abstract class MediaplayerActivity extends AppCompatActivity implements OnSeekBarChangeListener {
private static final String TAG = "MediaplayerActivity";
private static final String PREFS = "MediaPlayerActivityPreferences";
private static final String PREF_SHOW_TIME_LEFT = "showTimeLeft";
@@ -52,12 +66,17 @@ public abstract class MediaplayerActivity extends ActionBarActivity
protected TextView txtvPosition;
protected TextView txtvLength;
protected SeekBar sbPosition;
- protected ImageButton butPlay;
+ protected Button butPlaybackSpeed;
protected ImageButton butRev;
- protected boolean showTimeLeft = false;
protected TextView txtvRev;
+ protected ImageButton butPlay;
protected ImageButton butFF;
protected TextView txtvFF;
+ protected ImageButton butSkip;
+
+ protected boolean showTimeLeft = false;
+
+ private boolean isFavorite = false;
private PlaybackController newPlaybackController() {
return new PlaybackController(this, false) {
@@ -157,7 +176,7 @@ public abstract class MediaplayerActivity extends ActionBarActivity
}
protected void onPlaybackSpeedChange() {
-
+ updateButPlaybackSpeed();
}
protected void onServiceQueried() {
@@ -238,12 +257,6 @@ public abstract class MediaplayerActivity extends ActionBarActivity
}
}
- @Override
- protected void onDestroy() {
- super.onDestroy();
- Log.d(TAG, "onDestroy()");
- }
-
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onTrimMemory(int level) {
@@ -268,7 +281,7 @@ public abstract class MediaplayerActivity extends ActionBarActivity
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- if(controller == null) {
+ if (controller == null) {
return false;
}
Playable media = controller.getMedia();
@@ -294,19 +307,35 @@ public abstract class MediaplayerActivity extends ActionBarActivity
menu.findItem(R.id.share_item).setVisible(hasWebsiteLink || isItemAndHasLink || isItemHasDownloadLink);
- menu.findItem(R.id.skip_episode_item).setVisible(media != null);
+ menu.findItem(R.id.add_to_favorites_item).setVisible(false);
+ menu.findItem(R.id.remove_from_favorites_item).setVisible(false);
+ if(media != null && media instanceof FeedMedia) {
+ menu.findItem(R.id.add_to_favorites_item).setVisible(!isFavorite);
+ menu.findItem(R.id.remove_from_favorites_item).setVisible(isFavorite);
+ }
boolean sleepTimerSet = controller.sleepTimerActive();
boolean sleepTimerNotSet = controller.sleepTimerNotActive();
menu.findItem(R.id.set_sleeptimer_item).setVisible(sleepTimerNotSet);
menu.findItem(R.id.disable_sleeptimer_item).setVisible(sleepTimerSet);
+ if (this instanceof AudioplayerActivity) {
+ int[] attrs = {R.attr.action_bar_icon_color};
+ TypedArray ta = obtainStyledAttributes(UserPreferences.getTheme(), attrs);
+ int textColor = ta.getColor(0, Color.GRAY);
+ ta.recycle();
+ menu.findItem(R.id.audio_controls).setIcon(new IconDrawable(this,
+ FontAwesomeIcons.fa_sliders).color(textColor).actionBarSize());
+ } else {
+ menu.findItem(R.id.audio_controls).setVisible(false);
+ }
+
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if(controller == null) {
+ if (controller == null) {
return false;
}
Playable media = controller.getMedia();
@@ -317,84 +346,235 @@ public abstract class MediaplayerActivity extends ActionBarActivity
| Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
return true;
- } else if (media != null) {
- switch (item.getItemId()) {
- case R.id.disable_sleeptimer_item:
- if (controller.serviceAvailable()) {
-
- 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.positiveText(R.string.disable_sleeptimer_label);
- stDialog.negativeText(R.string.cancel_label);
- stDialog.callback(new MaterialDialog.ButtonCallback() {
+ } else {
+ if (media != null) {
+ switch (item.getItemId()) {
+ case R.id.add_to_favorites_item:
+ if(media instanceof FeedMedia) {
+ FeedItem feedItem = ((FeedMedia)media).getItem();
+ if(feedItem != null) {
+ DBWriter.addFavoriteItem(feedItem);
+ isFavorite = true;
+ invalidateOptionsMenu();
+ Toast.makeText(this, R.string.added_to_favorites, Toast.LENGTH_SHORT)
+ .show();
+ }
+ }
+ break;
+ case R.id.remove_from_favorites_item:
+ if(media instanceof FeedMedia) {
+ FeedItem feedItem = ((FeedMedia)media).getItem();
+ if(feedItem != null) {
+ DBWriter.removeFavoriteItem(feedItem);
+ isFavorite = false;
+ invalidateOptionsMenu();
+ Toast.makeText(this, R.string.removed_from_favorites, Toast.LENGTH_SHORT)
+ .show();
+ }
+ }
+ break;
+ case R.id.disable_sleeptimer_item:
+ if (controller.serviceAvailable()) {
+
+ 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.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) {
+ @Override
+ public void onTimerSet(long millis, boolean shakeToReset, boolean vibrate) {
+ controller.setSleepTimer(millis, shakeToReset, vibrate);
+ }
+ };
+ td.createNewDialog().show();
+ }
+ break;
+ case R.id.audio_controls:
+ MaterialDialog dialog = new MaterialDialog.Builder(this)
+ .title(R.string.audio_controls)
+ .customView(R.layout.audio_controls, false)
+ .neutralText(R.string.close_label)
+ .onNeutral((dialog1, which) -> {
+ final SeekBar left = (SeekBar) dialog1.findViewById(R.id.volume_left);
+ final SeekBar right = (SeekBar) dialog1.findViewById(R.id.volume_right);
+ UserPreferences.setVolume(left.getProgress(), right.getProgress());
+ })
+ .show();
+ final SeekBar barPlaybackSpeed = (SeekBar) dialog.findViewById(R.id.playback_speed);
+ final Button butDecSpeed = (Button) dialog.findViewById(R.id.butDecSpeed);
+ butDecSpeed.setOnClickListener(v -> {
+ if(controller != null && controller.canSetPlaybackSpeed()) {
+ barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() - 2);
+ } else {
+ VariableSpeedDialog.showGetPluginDialog(this);
+ }
+ });
+ final Button butIncSpeed = (Button) dialog.findViewById(R.id.butIncSpeed);
+ butIncSpeed.setOnClickListener(v -> {
+ if(controller != null && controller.canSetPlaybackSpeed()) {
+ barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() + 2);
+ } else {
+ VariableSpeedDialog.showGetPluginDialog(this);
+ }
+ });
+
+ final TextView txtvPlaybackSpeed = (TextView) dialog.findViewById(R.id.txtvPlaybackSpeed);
+ float currentSpeed = 1.0f;
+ try {
+ currentSpeed = Float.parseFloat(UserPreferences.getPlaybackSpeed());
+ } catch (NumberFormatException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ UserPreferences.setPlaybackSpeed(String.valueOf(currentSpeed));
+ }
+
+ txtvPlaybackSpeed.setText(String.format("%.2fx", currentSpeed));
+ barPlaybackSpeed.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
- public void onPositive(MaterialDialog dialog) {
- dialog.dismiss();
- controller.disableSleepTimer();
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if(controller != null && controller.canSetPlaybackSpeed()) {
+ float playbackSpeed = (progress + 10) / 20.0f;
+ controller.setPlaybackSpeed(playbackSpeed);
+ String speed = String.format("%.2f", playbackSpeed);
+ UserPreferences.setPlaybackSpeed(speed);
+ txtvPlaybackSpeed.setText(speed + "x");
+ } else if(fromUser) {
+ float speed = Float.valueOf(UserPreferences.getPlaybackSpeed());
+ barPlaybackSpeed.post(() -> {
+ barPlaybackSpeed.setProgress((int) (20 * speed) - 10);
+ });
+ }
}
@Override
- public void onNegative(MaterialDialog dialog) {
- dialog.dismiss();
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ if(controller != null && !controller.canSetPlaybackSpeed()) {
+ VariableSpeedDialog.showGetPluginDialog(MediaplayerActivity.this);
+ }
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
}
});
- stDialog.build().show();
- }
- break;
- case R.id.set_sleeptimer_item:
- if (controller.serviceAvailable()) {
- SleepTimerDialog td = new SleepTimerDialog(this) {
+ barPlaybackSpeed.setProgress((int) (20 * currentSpeed) - 10);
+
+ final SeekBar barLeftVolume = (SeekBar) dialog.findViewById(R.id.volume_left);
+ barLeftVolume.setProgress(100);
+ final SeekBar barRightVolume = (SeekBar) dialog.findViewById(R.id.volume_right);
+ barRightVolume.setProgress(100);
+ final CheckBox stereoToMono = (CheckBox) dialog.findViewById(R.id.stereo_to_mono);
+ stereoToMono.setChecked(UserPreferences.stereoToMono());
+ if (controller != null && !controller.canDownmix()) {
+ stereoToMono.setEnabled(false);
+ String sonicOnly = getString(R.string.sonic_only);
+ stereoToMono.setText(stereoToMono.getText() + " [" + sonicOnly + "]");
+ }
+
+ barLeftVolume.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
- public void onTimerSet(long millis, boolean shakeToReset, boolean vibrate) {
- controller.setSleepTimer(millis, shakeToReset, vibrate);
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ float leftVolume = 1.0f, rightVolume = 1.0f;
+ if (progress < 100) {
+ leftVolume = progress / 100.0f;
+ }
+ if (barRightVolume.getProgress() < 100) {
+ rightVolume = barRightVolume.getProgress() / 100.0f;
+ }
+ controller.setVolume(leftVolume, rightVolume);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
}
- };
- td.createNewDialog().show();
- }
- break;
- case R.id.visit_website_item:
- Uri uri = Uri.parse(media.getWebsiteLink());
- startActivity(new Intent(Intent.ACTION_VIEW, uri));
- break;
- case R.id.support_item:
- if (media instanceof FeedMedia) {
- DBTasks.flattrItemIfLoggedIn(this, ((FeedMedia) media).getItem());
- }
- break;
- case R.id.share_link_item:
- if (media instanceof FeedMedia) {
- ShareUtils.shareFeedItemLink(this, ((FeedMedia) media).getItem());
- }
- break;
- case R.id.share_download_url_item:
- if (media instanceof FeedMedia) {
- ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem());
- }
- break;
- case R.id.share_link_with_position_item:
- if (media instanceof FeedMedia) {
- ShareUtils.shareFeedItemLink(this, ((FeedMedia) media).getItem(), true);
- }
- break;
- case R.id.share_download_url_with_position_item:
- if (media instanceof FeedMedia) {
- ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem(), true);
- }
- break;
- case R.id.skip_episode_item:
- sendBroadcast(new Intent(
- PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
- break;
- default:
- return false;
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ barRightVolume.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ float leftVolume = 1.0f, rightVolume = 1.0f;
+ if (progress < 100) {
+ rightVolume = progress / 100.0f;
+ }
+ if (barLeftVolume.getProgress() < 100) {
+ leftVolume = barLeftVolume.getProgress() / 100.0f;
+ }
+ controller.setVolume(leftVolume, rightVolume);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ stereoToMono.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ UserPreferences.stereoToMono(isChecked);
+ if (controller != null) {
+ controller.setDownmix(isChecked);
+ }
+ });
+ break;
+ case R.id.visit_website_item:
+ Uri uri = Uri.parse(media.getWebsiteLink());
+ startActivity(new Intent(Intent.ACTION_VIEW, uri));
+ break;
+ case R.id.support_item:
+ if (media instanceof FeedMedia) {
+ DBTasks.flattrItemIfLoggedIn(this, ((FeedMedia) media).getItem());
+ }
+ break;
+ case R.id.share_link_item:
+ if (media instanceof FeedMedia) {
+ ShareUtils.shareFeedItemLink(this, ((FeedMedia) media).getItem());
+ }
+ break;
+ case R.id.share_download_url_item:
+ if (media instanceof FeedMedia) {
+ ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem());
+ }
+ break;
+ case R.id.share_link_with_position_item:
+ if (media instanceof FeedMedia) {
+ ShareUtils.shareFeedItemLink(this, ((FeedMedia) media).getItem(), true);
+ }
+ break;
+ case R.id.share_download_url_with_position_item:
+ if (media instanceof FeedMedia) {
+ ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem(), true);
+ }
+ break;
+ default:
+ return false;
+ }
+ return true;
+ } else {
+ return false;
}
- return true;
- } else {
- return false;
}
}
@@ -427,11 +607,10 @@ public abstract class MediaplayerActivity extends ActionBarActivity
&& controller.getMedia() != null) {
txtvPosition.setText(Converter
.getDurationStringLong(currentPosition));
- if(showTimeLeft) {
- txtvLength.setText("-"+Converter
+ if (showTimeLeft) {
+ txtvLength.setText("-" + Converter
.getDurationStringLong(duration - currentPosition));
- }
- else {
+ } else {
txtvLength.setText(Converter
.getDurationStringLong(duration));
}
@@ -443,7 +622,7 @@ public abstract class MediaplayerActivity extends ActionBarActivity
}
private void updateProgressbarPosition(int position, int duration) {
- Log.d(TAG, "updateProgressbarPosition(" + position + ", " + duration +")");
+ Log.d(TAG, "updateProgressbarPosition(" + position + ", " + duration + ")");
float progress = ((float) position) / duration;
sbPosition.setProgress((int) (progress * sbPosition.getMax()));
}
@@ -458,21 +637,32 @@ public abstract class MediaplayerActivity extends ActionBarActivity
Log.d(TAG, "loadMediaInfo()");
Playable media = controller.getMedia();
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
- showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT,false);
+ showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT, false);
if (media != null) {
- txtvPosition.setText(Converter.getDurationStringLong((media
- .getPosition())));
+ txtvPosition.setText(Converter.getDurationStringLong((media.getPosition())));
if (media.getDuration() != 0) {
- txtvLength.setText(Converter.getDurationStringLong(media
- .getDuration()));
- float progress = ((float) media.getPosition())
- / media.getDuration();
+ txtvLength.setText(Converter.getDurationStringLong(media.getDuration()));
+ float progress = ((float) media.getPosition()) / media.getDuration();
sbPosition.setProgress((int) (progress * sbPosition.getMax()));
- if(showTimeLeft) {
- txtvLength.setText("-"+Converter.getDurationStringLong((media
- .getDuration()-media.getPosition())));
+ if (showTimeLeft) {
+ int timeLeft = media.getDuration() - media.getPosition();
+ txtvLength.setText("-" + Converter.getDurationStringLong(timeLeft));
+ }
+ }
+ checkFavorite();
+ if(butPlaybackSpeed != null) {
+ if (controller == null) {
+ butPlaybackSpeed.setVisibility(View.GONE);
+ } else {
+ butPlaybackSpeed.setVisibility(View.VISIBLE);
+ if (controller.canSetPlaybackSpeed()) {
+ ViewCompat.setAlpha(butPlaybackSpeed, 1.0f);
+ } else {
+ ViewCompat.setAlpha(butPlaybackSpeed, 0.5f);
+ }
}
+ updateButPlaybackSpeed();
}
return true;
} else {
@@ -486,43 +676,43 @@ public abstract class MediaplayerActivity extends ActionBarActivity
txtvPosition = (TextView) findViewById(R.id.txtvPosition);
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
- showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT,false);
- Log.d("timeleft",showTimeLeft? "true":"false");
+ showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT, false);
+ Log.d("timeleft", showTimeLeft ? "true" : "false");
txtvLength = (TextView) findViewById(R.id.txtvLength);
- txtvLength.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- showTimeLeft = !showTimeLeft;
- Playable media = controller.getMedia();
- if (media == null) {
- return;
- }
-
- if (showTimeLeft) {
- txtvLength.setText("-"+Converter.getDurationStringLong((media
- .getDuration()-media.getPosition())));
- } else {
- txtvLength.setText(Converter.getDurationStringLong((media.getDuration())));
- }
+ txtvLength.setOnClickListener(v -> {
+ showTimeLeft = !showTimeLeft;
+ Playable media = controller.getMedia();
+ if (media == null) {
+ return;
+ }
- SharedPreferences.Editor editor = prefs.edit();
- editor.putBoolean(PREF_SHOW_TIME_LEFT,showTimeLeft);
- editor.apply();
- Log.d("timeleft on click",showTimeLeft? "true":"false");
+ String length;
+ if (showTimeLeft) {
+ length = "-" + Converter.getDurationStringLong(media.getDuration() - media.getPosition());
+ } else {
+ length = Converter.getDurationStringLong(media.getDuration());
}
+ txtvLength.setText(length);
+
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(PREF_SHOW_TIME_LEFT, showTimeLeft);
+ editor.apply();
+ Log.d("timeleft on click", showTimeLeft ? "true" : "false");
});
- butPlay = (ImageButton) findViewById(R.id.butPlay);
+ butPlaybackSpeed = (Button) findViewById(R.id.butPlaybackSpeed);
butRev = (ImageButton) findViewById(R.id.butRev);
txtvRev = (TextView) findViewById(R.id.txtvRev);
- if(txtvRev != null) {
+ if (txtvRev != null) {
txtvRev.setText(String.valueOf(UserPreferences.getRewindSecs()));
}
+ butPlay = (ImageButton) findViewById(R.id.butPlay);
butFF = (ImageButton) findViewById(R.id.butFF);
txtvFF = (TextView) findViewById(R.id.txtvFF);
- if(txtvFF != null) {
+ if (txtvFF != null) {
txtvFF.setText(String.valueOf(UserPreferences.getFastFowardSecs()));
}
+ butSkip = (ImageButton) findViewById(R.id.butSkip);
// SEEKBAR SETUP
@@ -530,92 +720,120 @@ public abstract class MediaplayerActivity extends ActionBarActivity
// BUTTON SETUP
- butPlay.setOnClickListener(controller.newOnPlayButtonClickListener());
+ if(butPlaybackSpeed != null) {
+ butPlaybackSpeed.setOnClickListener(v -> {
+ if (controller == null) {
+ return;
+ }
+ if (controller.canSetPlaybackSpeed()) {
+ String[] availableSpeeds = UserPreferences.getPlaybackSpeedArray();
+ String currentSpeed = UserPreferences.getPlaybackSpeed();
+
+ // Provide initial value in case the speed list has changed
+ // out from under us
+ // and our current speed isn't in the new list
+ String newSpeed;
+ if (availableSpeeds.length > 0) {
+ newSpeed = availableSpeeds[0];
+ } else {
+ newSpeed = "1.00";
+ }
- if (butFF != null) {
- butFF.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- int curr = controller.getPosition();
- controller.seekTo(curr + UserPreferences.getFastFowardSecs() * 1000);
+ for (int i = 0; i < availableSpeeds.length; i++) {
+ if (availableSpeeds[i].equals(currentSpeed)) {
+ if (i == availableSpeeds.length - 1) {
+ newSpeed = availableSpeeds[0];
+ } else {
+ newSpeed = availableSpeeds[i + 1];
+ }
+ break;
+ }
+ }
+ UserPreferences.setPlaybackSpeed(newSpeed);
+ controller.setPlaybackSpeed(Float.parseFloat(newSpeed));
+ } else {
+ VariableSpeedDialog.showGetPluginDialog(this);
}
});
- butFF.setOnLongClickListener(new View.OnLongClickListener() {
+ butPlaybackSpeed.setOnLongClickListener(v -> {
+ VariableSpeedDialog.showDialog(this);
+ return true;
+ });
+ }
+
+ if (butRev != null) {
+ butRev.setOnClickListener(v -> {
+ int curr = controller.getPosition();
+ controller.seekTo(curr - UserPreferences.getRewindSecs() * 1000);
+ });
+ butRev.setOnLongClickListener(new View.OnLongClickListener() {
int choice;
@Override
public boolean onLongClick(View v) {
int checked = 0;
- int rewindSecs = UserPreferences.getFastFowardSecs();
+ int rewindSecs = UserPreferences.getRewindSecs();
final int[] values = getResources().getIntArray(R.array.seek_delta_values);
final String[] choices = new String[values.length];
- for(int i=0; i < values.length; i++) {
+ for (int i = 0; i < values.length; i++) {
if (rewindSecs == values[i]) {
checked = i;
}
- choices[i] = String.valueOf(values[i]) + " "
- + getString(R.string.time_seconds);
+ choices[i] = String.valueOf(values[i]) + " " + getString(R.string.time_seconds);
}
choice = values[checked];
AlertDialog.Builder builder = new AlertDialog.Builder(MediaplayerActivity.this);
- builder.setTitle(R.string.pref_fast_forward);
+ builder.setTitle(R.string.pref_rewind);
builder.setSingleChoiceItems(choices, checked,
(dialog, which) -> {
choice = values[which];
});
builder.setNegativeButton(R.string.cancel_label, null);
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- UserPreferences.setPrefFastForwardSecs(choice);
- txtvFF.setText(String.valueOf(choice));
+ UserPreferences.setPrefRewindSecs(choice);
+ txtvRev.setText(String.valueOf(choice));
});
builder.create().show();
return true;
}
});
}
- if (butRev != null) {
- butRev.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- int curr = controller.getPosition();
- controller.seekTo(curr - UserPreferences.getRewindSecs() * 1000);
- }
+
+ butPlay.setOnClickListener(controller.newOnPlayButtonClickListener());
+
+ if (butFF != null) {
+ butFF.setOnClickListener(v -> {
+ int curr = controller.getPosition();
+ controller.seekTo(curr + UserPreferences.getFastFowardSecs() * 1000);
});
- butRev.setOnLongClickListener(new View.OnLongClickListener() {
+ butFF.setOnLongClickListener(new View.OnLongClickListener() {
int choice;
@Override
public boolean onLongClick(View v) {
int checked = 0;
- int rewindSecs = UserPreferences.getRewindSecs();
+ int rewindSecs = UserPreferences.getFastFowardSecs();
final int[] values = getResources().getIntArray(R.array.seek_delta_values);
final String[] choices = new String[values.length];
- for(int i=0; i < values.length; i++) {
+ for (int i = 0; i < values.length; i++) {
if (rewindSecs == values[i]) {
checked = i;
}
- choices[i] = String.valueOf(values[i]) + " "
- + getString(R.string.time_seconds);
+ choices[i] = String.valueOf(values[i]) + " " + getString(R.string.time_seconds);
}
choice = values[checked];
AlertDialog.Builder builder = new AlertDialog.Builder(MediaplayerActivity.this);
- builder.setTitle(R.string.pref_rewind);
+ builder.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.setPrefRewindSecs(choice);
- txtvRev.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;
@@ -623,6 +841,11 @@ public abstract class MediaplayerActivity extends ActionBarActivity
});
}
+ if (butSkip != null) {
+ butSkip.setOnClickListener(v -> {
+ sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
+ });
+ }
}
protected abstract int getContentViewResourceId();
@@ -633,12 +856,9 @@ public abstract class MediaplayerActivity extends ActionBarActivity
errorDialog
.setMessage(MediaPlayerError.getErrorString(this, errorCode));
errorDialog.setNeutralButton("OK",
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- finish();
- }
+ (dialog, which) -> {
+ dialog.dismiss();
+ finish();
}
);
errorDialog.create().show();
@@ -647,19 +867,23 @@ public abstract class MediaplayerActivity extends ActionBarActivity
float prog;
@Override
- public void onProgressChanged(SeekBar seekBar, int progress,
- boolean fromUser) {
+ public void onProgressChanged (SeekBar seekBar,int progress, boolean fromUser) {
if (controller != null) {
- prog = controller.onSeekBarProgressChanged(seekBar, progress, fromUser,
- txtvPosition);
- if(showTimeLeft && prog!=0) {
+ prog = controller.onSeekBarProgressChanged(seekBar, progress, fromUser, txtvPosition);
+ if (showTimeLeft && prog != 0) {
int duration = controller.getDuration();
- txtvLength.setText("-"+Converter
- .getDurationStringLong(duration - (int) (prog * duration)));
+ String length = "-" + Converter.getDurationStringLong(duration - (int) (prog * duration));
+ txtvLength.setText(length);
}
}
}
+ private void updateButPlaybackSpeed() {
+ if (controller != null && butPlaybackSpeed != null) {
+ butPlaybackSpeed.setText(UserPreferences.getPlaybackSpeed() + "x");
+ }
+ }
+
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
if (controller != null) {
@@ -674,4 +898,23 @@ public abstract class MediaplayerActivity extends ActionBarActivity
}
}
+ private void checkFavorite() {
+ Playable playable = controller.getMedia();
+ if (playable != null && playable instanceof FeedMedia) {
+ FeedItem feedItem = ((FeedMedia) playable).getItem();
+ if (feedItem != null) {
+ Observable.fromCallable(() -> DBReader.getFeedItem(feedItem.getId()))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(item -> {
+ boolean isFav = item.isTagged(FeedItem.TAG_FAVORITE);
+ if(isFavorite != isFav) {
+ isFavorite = isFav;
+ invalidateOptionsMenu();
+ }
+ });
+ }
+ }
+ }
+
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java
index 60eb290b5..ee459dbc6 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java
@@ -3,9 +3,9 @@ package de.danoeh.antennapod.activity;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
-import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.support.v4.view.WindowCompat;
import android.util.Log;
import android.util.Pair;
@@ -19,7 +19,9 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.SeekBar;
-import de.danoeh.antennapod.BuildConfig;
+import java.lang.ref.WeakReference;
+import java.util.concurrent.atomic.AtomicBoolean;
+
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
@@ -39,8 +41,12 @@ public class VideoplayerActivity extends MediaplayerActivity {
*/
private boolean videoControlsShowing = true;
private boolean videoSurfaceCreated = false;
- private VideoControlsHider videoControlsToggler;
+ private VideoControlsHider videoControlsHider = new VideoControlsHider(this);
+
+ private AtomicBoolean isSetup = new AtomicBoolean(false);
+
+ private LinearLayout controls;
private LinearLayout videoOverlay;
private AspectRatioVideoView videoview;
private ProgressBar progressIndicator;
@@ -61,25 +67,12 @@ public class VideoplayerActivity extends MediaplayerActivity {
}
@Override
- protected void onPause() {
- super.onPause();
- if (videoControlsToggler != null) {
- videoControlsToggler.cancel(true);
- }
- if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) {
- controller.pause();
- }
- }
-
- @Override
protected void onResume() {
super.onResume();
if (getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_VIEW)) {
Intent intent = getIntent();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received VIEW intent: "
- + intent.getData().getPath());
+ Log.d(TAG, "Received VIEW intent: " + intent.getData().getPath());
ExternalMedia media = new ExternalMedia(intent.getData().getPath(),
MediaType.VIDEO);
Intent launchIntent = new Intent(this, PlaybackService.class);
@@ -94,6 +87,22 @@ public class VideoplayerActivity extends MediaplayerActivity {
}
@Override
+ protected void onPause() {
+ super.onPause();
+ videoControlsHider.stop();
+ if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) {
+ controller.pause();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ videoControlsHider.stop();
+ videoControlsHider = null;
+ }
+
+ @Override
protected boolean loadMediaInfo() {
if (!super.loadMediaInfo()) {
return false;
@@ -104,14 +113,17 @@ public class VideoplayerActivity extends MediaplayerActivity {
getSupportActionBar().setTitle(media.getFeedTitle());
return true;
}
-
return false;
}
@Override
protected void setupGUI() {
+ if(isSetup.getAndSet(true)) {
+ return;
+ }
super.setupGUI();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ controls = (LinearLayout) findViewById(R.id.controls);
videoOverlay = (LinearLayout) findViewById(R.id.overlay);
videoview = (AspectRatioVideoView) findViewById(R.id.videoview);
progressIndicator = (ProgressBar) findViewById(R.id.progressIndicator);
@@ -133,14 +145,11 @@ public class VideoplayerActivity extends MediaplayerActivity {
@Override
protected void onAwaitingVideoSurface() {
if (videoSurfaceCreated) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Videosurface already created, setting videosurface now");
+ Log.d(TAG, "Videosurface already created, setting videosurface now");
Pair<Integer, Integer> videoSize = controller.getVideoSize();
if (videoSize != null && videoSize.first > 0 && videoSize.second > 0) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Width,height of video: " + videoSize.first + ", " + videoSize.second);
+ Log.d(TAG, "Width,height of video: " + videoSize.first + ", " + videoSize.second);
videoview.setVideoSize(videoSize.first, videoSize.second);
} else {
Log.e(TAG, "Could not determine video size");
@@ -156,7 +165,6 @@ public class VideoplayerActivity extends MediaplayerActivity {
} else {
progressIndicator.setVisibility(View.INVISIBLE);
}
-
}
@Override
@@ -164,38 +172,23 @@ public class VideoplayerActivity extends MediaplayerActivity {
progressIndicator.setVisibility(View.INVISIBLE);
}
- View.OnTouchListener onVideoviewTouched = new View.OnTouchListener() {
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- if (videoControlsToggler != null) {
- videoControlsToggler.cancel(true);
- }
- toggleVideoControlsVisibility();
- if (videoControlsShowing) {
- setupVideoControlsToggler();
- }
-
- return true;
- } else {
- return false;
+ View.OnTouchListener onVideoviewTouched = (v, event) -> {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ videoControlsHider.stop();
+ toggleVideoControlsVisibility();
+ if (videoControlsShowing) {
+ setupVideoControlsToggler();
}
+ return true;
+ } else {
+ return false;
}
};
@SuppressLint("NewApi")
void setupVideoControlsToggler() {
- if (videoControlsToggler != null) {
- videoControlsToggler.cancel(true);
- }
- videoControlsToggler = new VideoControlsHider();
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- videoControlsToggler
- .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- videoControlsToggler.execute();
- }
+ videoControlsHider.stop();
+ videoControlsHider.start();
}
private void toggleVideoControlsVisibility() {
@@ -209,46 +202,6 @@ public class VideoplayerActivity extends MediaplayerActivity {
videoControlsShowing = !videoControlsShowing;
}
- /**
- * Hides the videocontrols after a certain period of time.
- */
- public class VideoControlsHider extends AsyncTask<Void, Void, Void> {
- @Override
- protected void onCancelled() {
- videoControlsToggler = null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- videoControlsToggler = null;
- }
-
- private static final int WAITING_INTERVALL = 5000;
- private static final String TAG = "VideoControlsToggler";
-
- @Override
- protected void onProgressUpdate(Void... values) {
- if (videoControlsShowing) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Hiding video controls");
- getSupportActionBar().hide();
- hideVideoControls();
- videoControlsShowing = false;
- }
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- try {
- Thread.sleep(WAITING_INTERVALL);
- } catch (InterruptedException e) {
- return null;
- }
- publishProgress();
- return null;
- }
-
- }
private final SurfaceHolder.Callback surfaceHolderCallback = new SurfaceHolder.Callback() {
@Override
@@ -259,15 +212,13 @@ public class VideoplayerActivity extends MediaplayerActivity {
@Override
public void surfaceCreated(SurfaceHolder holder) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Videoview holder created");
+ Log.d(TAG, "Videoview holder created");
videoSurfaceCreated = true;
if (controller.getStatus() == PlayerStatus.PLAYING) {
if (controller.serviceAvailable()) {
controller.setVideoSurface(holder);
} else {
- Log.e(TAG,
- "Could'nt attach surface to mediaplayer - reference to service was null");
+ Log.e(TAG, "Could'nt attach surface to mediaplayer - reference to service was null");
}
}
@@ -275,8 +226,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Videosurface was destroyed");
+ Log.d(TAG, "Videosurface was destroyed");
videoSurfaceCreated = false;
controller.notifyVideoSurfaceAbandoned();
}
@@ -286,9 +236,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
@Override
protected void onReloadNotification(int notificationCode) {
if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "ReloadNotification received, switching to Audioplayer now");
+ Log.d(TAG, "ReloadNotification received, switching to Audioplayer now");
finish();
startActivity(new Intent(this, AudioplayerActivity.class));
}
@@ -297,9 +245,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
super.onStartTrackingTouch(seekBar);
- if (videoControlsToggler != null) {
- videoControlsToggler.cancel(true);
- }
+ videoControlsHider.stop();
}
@Override
@@ -321,12 +267,11 @@ public class VideoplayerActivity extends MediaplayerActivity {
@SuppressLint("NewApi")
private void showVideoControls() {
videoOverlay.setVisibility(View.VISIBLE);
- butPlay.setVisibility(View.VISIBLE);
- final Animation animation = AnimationUtils.loadAnimation(this,
- R.anim.fade_in);
+ controls.setVisibility(View.VISIBLE);
+ final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_in);
if (animation != null) {
videoOverlay.startAnimation(animation);
- butPlay.startAnimation(animation);
+ controls.startAnimation(animation);
}
if (Build.VERSION.SDK_INT >= 14) {
videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
@@ -335,11 +280,10 @@ public class VideoplayerActivity extends MediaplayerActivity {
@SuppressLint("NewApi")
private void hideVideoControls() {
- final Animation animation = AnimationUtils.loadAnimation(this,
- R.anim.fade_out);
+ final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_out);
if (animation != null) {
videoOverlay.startAnimation(animation);
- butPlay.startAnimation(animation);
+ controls.startAnimation(animation);
}
if (Build.VERSION.SDK_INT >= 14) {
int videoviewFlag = (Build.VERSION.SDK_INT >= 16) ? View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION : 0;
@@ -348,7 +292,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
videoOverlay.setFitsSystemWindows(true);
}
videoOverlay.setVisibility(View.GONE);
- butPlay.setVisibility(View.GONE);
+ controls.setVisibility(View.GONE);
}
@Override
@@ -356,7 +300,6 @@ public class VideoplayerActivity extends MediaplayerActivity {
return R.layout.videoplayer_activity;
}
-
@Override
protected void setScreenOn(boolean enable) {
super.setScreenOn(enable);
@@ -366,4 +309,38 @@ public class VideoplayerActivity extends MediaplayerActivity {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
}
+
+ private static class VideoControlsHider extends Handler {
+
+ private static final int DELAY = 5000;
+
+ private WeakReference<VideoplayerActivity> activity;
+
+ public VideoControlsHider(VideoplayerActivity activity) {
+ this.activity = new WeakReference<>(activity);
+ }
+
+ private final Runnable hideVideoControls = () -> {
+ VideoplayerActivity vpa = activity.get();
+ if(vpa == null) {
+ return;
+ }
+ if (vpa.videoControlsShowing) {
+ Log.d(TAG, "Hiding video controls");
+ vpa.getSupportActionBar().hide();
+ vpa.hideVideoControls();
+ vpa.videoControlsShowing = false;
+ }
+ };
+
+ public void start() {
+ this.postDelayed(hideVideoControls, DELAY);
+ }
+
+ public void stop() {
+ this.removeCallbacks(hideVideoControls);
+ }
+
+ }
+
}
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 1fa4b7c48..d749b0313 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
@@ -35,6 +35,7 @@ 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.DateUtils;
+import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.fragment.ItemFragment;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
@@ -328,8 +329,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
item1.setVisible(visible);
}
};
- FeedItemMenuHandler.onPrepareMenu(mainActivityRef.get(), contextMenuInterface, item, true,
- null);
+ FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true,
+ itemAccess.getQueueIds(), itemAccess.getFavoritesIds());
}
}
@@ -344,6 +345,10 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
boolean isInQueue(FeedItem item);
+ LongList getQueueIds();
+
+ LongList getFavoritesIds();
+
}
/**
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ChapterListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/ChapterListAdapter.java
deleted file mode 100644
index cf0532cf1..000000000
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ChapterListAdapter.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.Context;
-import android.text.Layout;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.style.ClickableSpan;
-import android.text.util.Linkify;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ImageButton;
-import android.widget.TextView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.feed.Chapter;
-import de.danoeh.antennapod.core.util.ChapterUtils;
-import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.playback.Playable;
-
-import java.util.List;
-
-public class ChapterListAdapter extends ArrayAdapter<Chapter> {
-
- private static final String TAG = "ChapterListAdapter";
-
- private List<Chapter> chapters;
- private Playable media;
-
- private int defaultTextColor;
- private final Callback callback;
-
- public ChapterListAdapter(Context context, int textViewResourceId,
- List<Chapter> objects, Playable media, Callback callback) {
- super(context, textViewResourceId, objects);
- this.chapters = objects;
- this.media = media;
- this.callback = callback;
- }
-
- @Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- Holder holder;
-
- Chapter sc = getItem(position);
-
- // Inflate Layout
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) getContext()
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- convertView = inflater.inflate(R.layout.simplechapter_item, parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- defaultTextColor = holder.title.getTextColors().getDefaultColor();
- holder.start = (TextView) convertView.findViewById(R.id.txtvStart);
- holder.link = (TextView) convertView.findViewById(R.id.txtvLink);
- holder.butPlayChapter = (ImageButton) convertView.findViewById(R.id.butPlayChapter);
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
-
- }
-
- holder.title.setText(sc.getTitle());
- holder.start.setText(Converter.getDurationStringLong((int) sc
- .getStart()));
- if (sc.getLink() != null) {
- holder.link.setVisibility(View.VISIBLE);
- holder.link.setText(sc.getLink());
- Linkify.addLinks(holder.link, Linkify.WEB_URLS);
- } else {
- holder.link.setVisibility(View.GONE);
- }
- holder.link.setMovementMethod(null);
- holder.link.setOnTouchListener(new OnTouchListener() {
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- // from
- // http://stackoverflow.com/questions/7236840/android-textview-linkify-intercepts-with-parent-view-gestures
- TextView widget = (TextView) v;
- Object text = widget.getText();
- if (text instanceof Spanned) {
- Spannable buffer = (Spannable) text;
-
- int action = event.getAction();
-
- if (action == MotionEvent.ACTION_UP
- || action == MotionEvent.ACTION_DOWN) {
- int x = (int) event.getX();
- int y = (int) event.getY();
-
- x -= widget.getTotalPaddingLeft();
- y -= widget.getTotalPaddingTop();
-
- x += widget.getScrollX();
- y += widget.getScrollY();
-
- Layout layout = widget.getLayout();
- int line = layout.getLineForVertical(y);
- int off = layout.getOffsetForHorizontal(line, x);
-
- ClickableSpan[] link = buffer.getSpans(off, off,
- ClickableSpan.class);
-
- if (link.length != 0) {
- if (action == MotionEvent.ACTION_UP) {
- link[0].onClick(widget);
- } else if (action == MotionEvent.ACTION_DOWN) {
- Selection.setSelection(buffer,
- buffer.getSpanStart(link[0]),
- buffer.getSpanEnd(link[0]));
- }
- return true;
- }
- }
-
- }
-
- return false;
-
- }
- });
- holder.butPlayChapter.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (callback != null) {
- callback.onPlayChapterButtonClicked(position);
- }
- }
- });
- Chapter current = ChapterUtils.getCurrentChapter(media);
- if (current != null) {
- if (current == sc) {
- holder.title.setTextColor(convertView.getResources().getColor(
- R.color.holo_blue_light));
- holder.start.setTextColor(convertView.getResources().getColor(
- R.color.holo_blue_light));
- } else {
- holder.title.setTextColor(defaultTextColor);
- holder.start.setTextColor(defaultTextColor);
- }
- } else {
- Log.w(TAG, "Could not find out what the current chapter is.");
- }
-
- return convertView;
- }
-
- static class Holder {
- TextView title;
- TextView start;
- TextView link;
- ImageButton butPlayChapter;
- }
-
- @Override
- public int getCount() {
- // ignore invalid chapters
- int counter = 0;
- if (chapters != null) {
- for (Chapter chapter : chapters) {
- if (!ignoreChapter(chapter)) {
- counter++;
- }
- }
- }
- return counter;
- }
-
- private boolean ignoreChapter(Chapter c) {
- return media.getDuration() > 0 && media.getDuration() < c.getStart();
- }
-
- @Override
- public Chapter getItem(int position) {
- int i = 0;
- for (Chapter chapter : chapters) {
- if (!ignoreChapter(chapter)) {
- if (i == position) {
- return chapter;
- } else {
- i++;
- }
- }
- }
- return super.getItem(position);
- }
-
- public static interface Callback {
- public void onPlayChapterButtonClicked(int position);
- }
-
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
new file mode 100644
index 000000000..1c9439ee6
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
@@ -0,0 +1,198 @@
+package de.danoeh.antennapod.adapter;
+
+import android.content.Context;
+import android.text.Layout;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.Spanned;
+import android.text.style.ClickableSpan;
+import android.text.util.Linkify;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.feed.Chapter;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.util.ChapterUtils;
+import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.playback.Playable;
+
+public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
+
+ private static final String TAG = "ChapterListAdapter";
+
+ private Playable media;
+
+ private int defaultTextColor;
+ private final Callback callback;
+
+ public ChaptersListAdapter(Context context, int textViewResourceId, Callback callback) {
+ super(context, textViewResourceId);
+ this.callback = callback;
+ }
+
+ public void setMedia(Playable media) {
+ this.media = media;
+ }
+
+ @Override
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ Holder holder;
+
+ Chapter sc = getItem(position);
+
+ // Inflate Layout
+ if (convertView == null) {
+ holder = new Holder();
+ LayoutInflater inflater = (LayoutInflater) getContext()
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ convertView = inflater.inflate(R.layout.simplechapter_item, parent, false);
+ holder.view = convertView;
+ holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
+ defaultTextColor = holder.title.getTextColors().getDefaultColor();
+ holder.start = (TextView) convertView.findViewById(R.id.txtvStart);
+ holder.link = (TextView) convertView.findViewById(R.id.txtvLink);
+ holder.butPlayChapter = (ImageButton) convertView.findViewById(R.id.butPlayChapter);
+ convertView.setTag(holder);
+ } else {
+ holder = (Holder) convertView.getTag();
+
+ }
+
+ holder.title.setText(sc.getTitle());
+ holder.start.setText(Converter.getDurationStringLong((int) sc
+ .getStart()));
+ if (sc.getLink() != null) {
+ holder.link.setVisibility(View.VISIBLE);
+ holder.link.setText(sc.getLink());
+ Linkify.addLinks(holder.link, Linkify.WEB_URLS);
+ } else {
+ holder.link.setVisibility(View.GONE);
+ }
+ holder.link.setMovementMethod(null);
+ holder.link.setOnTouchListener((v, event) -> {
+ // from
+ // http://stackoverflow.com/questions/7236840/android-textview-linkify-intercepts-with-parent-view-gestures
+ TextView widget = (TextView) v;
+ Object text = widget.getText();
+ if (text instanceof Spanned) {
+ Spannable buffer = (Spannable) text;
+
+ int action = event.getAction();
+
+ if (action == MotionEvent.ACTION_UP
+ || action == MotionEvent.ACTION_DOWN) {
+ int x = (int) event.getX();
+ int y = (int) event.getY();
+
+ x -= widget.getTotalPaddingLeft();
+ y -= widget.getTotalPaddingTop();
+
+ x += widget.getScrollX();
+ y += widget.getScrollY();
+
+ Layout layout = widget.getLayout();
+ int line = layout.getLineForVertical(y);
+ int off = layout.getOffsetForHorizontal(line, x);
+
+ ClickableSpan[] link = buffer.getSpans(off, off,
+ ClickableSpan.class);
+
+ if (link.length != 0) {
+ if (action == MotionEvent.ACTION_UP) {
+ link[0].onClick(widget);
+ } else if (action == MotionEvent.ACTION_DOWN) {
+ Selection.setSelection(buffer,
+ buffer.getSpanStart(link[0]),
+ buffer.getSpanEnd(link[0]));
+ }
+ return true;
+ }
+ }
+
+ }
+
+ return false;
+
+ });
+ holder.butPlayChapter.setOnClickListener(v -> {
+ if (callback != null) {
+ callback.onPlayChapterButtonClicked(position);
+ }
+ });
+ Chapter current = ChapterUtils.getCurrentChapter(media);
+ if (current != null) {
+ if (current == sc) {
+ int playingBackGroundColor;
+ if(UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
+ playingBackGroundColor = getContext().getResources().getColor(R.color.highlight_dark);
+ } else {
+ playingBackGroundColor = getContext().getResources().getColor(R.color.highlight_light);
+ }
+ holder.view.setBackgroundColor(playingBackGroundColor);
+ } else {
+ holder.view.setBackgroundColor(getContext().getResources().getColor(android.R.color.transparent));
+ holder.title.setTextColor(defaultTextColor);
+ holder.start.setTextColor(defaultTextColor);
+ }
+ } else {
+ Log.w(TAG, "Could not find out what the current chapter is.");
+ }
+
+ return convertView;
+ }
+
+ static class Holder {
+ View view;
+ TextView title;
+ TextView start;
+ TextView link;
+ ImageButton butPlayChapter;
+ }
+
+ @Override
+ public int getCount() {
+ if(media == null || media.getChapters() == null) {
+ return 0;
+ }
+ // ignore invalid chapters
+ int counter = 0;
+ for (Chapter chapter : media.getChapters()) {
+ if (!ignoreChapter(chapter)) {
+ counter++;
+ }
+ }
+ return counter;
+ }
+
+ private boolean ignoreChapter(Chapter c) {
+ return media.getDuration() > 0 && media.getDuration() < c.getStart();
+ }
+
+ @Override
+ public Chapter getItem(int position) {
+ int i = 0;
+ for (Chapter chapter : media.getChapters()) {
+ if (!ignoreChapter(chapter)) {
+ if (i == position) {
+ return chapter;
+ } else {
+ i++;
+ }
+ }
+ }
+ return super.getItem(position);
+ }
+
+ public interface Callback {
+ void onPlayChapterButtonClicked(int position);
+ }
+
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
index 9011c8b02..5b205e91f 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
@@ -6,11 +6,13 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.feed.FeedItem;
import java.util.List;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.util.DateUtils;
+
/**
* List adapter for showing a list of FeedItems with their title and description.
*/
@@ -33,6 +35,7 @@ public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.itemdescription_listitem, parent, false);
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
+ holder.pubDate = (TextView) convertView.findViewById(R.id.txtvPubDate);
holder.description = (TextView) convertView.findViewById(R.id.txtvDescription);
convertView.setTag(holder);
@@ -41,15 +44,20 @@ public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
}
holder.title.setText(item.getTitle());
+ holder.pubDate.setText(DateUtils.formatAbbrev(getContext(), item.getPubDate()));
if (item.getDescription() != null) {
- holder.description.setText(item.getDescription());
+ String description = item.getDescription()
+ .replaceAll("\n", " ")
+ .replaceAll("\\s+", " ")
+ .trim();
+ holder.description.setText(description);
}
-
return convertView;
}
static class Holder {
TextView title;
+ TextView pubDate;
TextView description;
}
}
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 ca1f59e8d..d0266be6d 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
@@ -183,8 +183,8 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
item1.setVisible(visible);
}
};
- FeedItemMenuHandler.onPrepareMenu(mainActivity.get(), contextMenuInterface, item, true,
- itemAccess.getQueueIds());
+ FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true,
+ itemAccess.getQueueIds(), itemAccess.getFavoritesIds());
}
@Override
@@ -351,6 +351,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
long getItemDownloadSize(FeedItem item);
int getItemDownloadProgressPercent(FeedItem item);
LongList getQueueIds();
+ LongList getFavoritesIds();
}
/**
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
index 08ffdd197..47ac4c757 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
@@ -10,6 +10,7 @@ import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -65,6 +66,12 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
//Set the title
viewHolder.titleView.setText(podcast.title);
+ if(!podcast.feedUrl.contains("itunes.apple.com")) {
+ viewHolder.urlView.setText(podcast.feedUrl);
+ viewHolder.urlView.setVisibility(View.VISIBLE);
+ } else {
+ viewHolder.urlView.setVisibility(View.GONE);
+ }
//Update the empty imageView with the image from the feed
Glide.with(context)
@@ -94,6 +101,8 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
*/
public final TextView titleView;
+ public final TextView urlView;
+
/**
* Constructor
@@ -102,6 +111,7 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
PodcastViewHolder(View view){
coverView = (ImageView) view.findViewById(R.id.imgvCover);
titleView = (TextView) view.findViewById(R.id.txtvTitle);
+ urlView = (TextView) view.findViewById(R.id.txtvUrl);
}
}
@@ -124,16 +134,47 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
*/
public final String feedUrl;
+
+ private Podcast(String title, String imageUrl, String feedUrl) {
+ this.title = title;
+ this.imageUrl = imageUrl;
+ this.feedUrl = feedUrl;
+ }
+
+ /**
+ * Constructs a Podcast instance from a iTunes search result
+ *
+ * @param json object holding the podcast information
+ * @throws JSONException
+ */
+ public static Podcast fromSearch(JSONObject json) throws JSONException {
+ String title = json.getString("collectionName");
+ String imageUrl = json.getString("artworkUrl100");
+ String feedUrl = json.getString("feedUrl");
+ return new Podcast(title, imageUrl, feedUrl);
+ }
+
/**
- * Constructor.
+ * Constructs a Podcast instance from iTunes toplist entry
*
* @param json object holding the podcast information
* @throws JSONException
*/
- public Podcast(JSONObject json) throws JSONException {
- title = json.getString("collectionName");
- imageUrl = json.getString("artworkUrl100");
- feedUrl = json.getString("feedUrl");
+ public static Podcast fromToplist(JSONObject json) throws JSONException {
+ String title = json.getJSONObject("title").getString("label");
+ String imageUrl = null;
+ JSONArray images = json.getJSONArray("im:image");
+ for(int i=0; imageUrl == null && i < images.length(); i++) {
+ JSONObject image = images.getJSONObject(i);
+ String height = image.getJSONObject("attributes").getString("height");
+ if(Integer.valueOf(height) >= 100) {
+ imageUrl = image.getString("label");
+ }
+ }
+ String feedUrl = "https://itunes.apple.com/lookup?id=" +
+ json.getJSONObject("id").getJSONObject("attributes").getString("im:id");
+ return new Podcast(title, imageUrl, feedUrl);
}
+
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
index 16909cbb3..6432ebd4e 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
@@ -2,6 +2,7 @@ package de.danoeh.antennapod.dialog;
import android.content.res.TypedArray;
import android.graphics.Color;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
@@ -126,9 +127,6 @@ public class EpisodesApplyActionFragment extends Fragment {
textColor = ta.getColor(0, Color.GRAY);
ta.recycle();
- menu.findItem(R.id.sort).setIcon(new IconDrawable(getActivity(),
- FontAwesomeIcons.fa_sort).color(textColor).actionBarSize());
-
mSelectToggle = menu.findItem(R.id.select_toggle);
mSelectToggle.setOnMenuItemClickListener(item -> {
if (checkedIds.size() == episodes.size()) {
@@ -138,23 +136,27 @@ public class EpisodesApplyActionFragment extends Fragment {
}
return true;
});
-
- menu.findItem(R.id.select_options).setIcon(new IconDrawable(getActivity(),
- FontAwesomeIcons.fa_caret_down).color(textColor).actionBarSize());
}
@Override
public void onPrepareOptionsMenu (Menu menu) {
- Icon icon;
- if(checkedIds.size() == episodes.size()) {
- icon = FontAwesomeIcons.fa_check_square_o;
- } else if(checkedIds.size() == 0) {
- icon = FontAwesomeIcons.fa_square_o;
- } else {
- icon = FontAwesomeIcons.fa_minus_square_o;
- }
- mSelectToggle.setIcon(new IconDrawable(getActivity(), icon).color(textColor).actionBarSize());
-
+ /*
+ * Prepare icon for select toggle button
+ */
+
+ // Find icon attribute
+ int[] icon = new int[1];
+ if(checkedIds.size() == episodes.size()) icon[0] = R.attr.ic_check_box;
+ else if(checkedIds.size() == 0) icon[0] = R.attr.ic_check_box_outline;
+ else icon[0] = R.attr.ic_indeterminate_check_box;
+
+ // Get Drawable from attribute
+ TypedArray a = getActivity().obtainStyledAttributes(icon);
+ Drawable iconDrawable = a.getDrawable(0);
+ a.recycle();
+
+ // Set icon
+ mSelectToggle.setIcon(iconDrawable);
}
@Override
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 4b512a48d..3ed82b9bd 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
@@ -21,107 +21,104 @@ import de.danoeh.antennapod.core.util.IntentUtils;
public class VariableSpeedDialog {
- private static final String TAG = VariableSpeedDialog.class.getSimpleName();
-
- private static final Intent playStoreIntent = new Intent(Intent.ACTION_VIEW,
- Uri.parse("market://details?id=com.falconware.prestissimo"));
-
- private VariableSpeedDialog() {
- }
-
- public static void showDialog(final Context context) {
- if (org.antennapod.audio.MediaPlayer.isPrestoLibraryInstalled(context)
- || UserPreferences.useSonic()) {
- showSpeedSelectorDialog(context);
- } else {
- showGetPluginDialog(context);
- }
- }
-
- private static void showGetPluginDialog(final Context context) {
- MaterialDialog.Builder builder = new MaterialDialog.Builder(context);
- builder.title(R.string.no_playback_plugin_title);
- builder.content(R.string.no_playback_plugin_or_sonic_msg);
- builder.positiveText(R.string.download_plugin_label);
- builder.negativeText(R.string.enable_sonic);
- builder.neutralText(R.string.close_label);
- builder.callback(new MaterialDialog.ButtonCallback() {
- @Override
- public void onPositive(MaterialDialog dialog) {
- try {
- context.startActivity(playStoreIntent);
- } catch (ActivityNotFoundException e) {
- // this is usually thrown on an emulator if the Android market is not installed
- Log.e(TAG, Log.getStackTraceString(e));
- }
- }
-
- @Override
- public void onNegative(MaterialDialog dialog) {
- if (Build.VERSION.SDK_INT >= 16) { // just to be safe
- UserPreferences.enableSonic(true);
- showSpeedSelectorDialog(context);
- }
- }
-
- @Override
- public void onNeutral(MaterialDialog dialog) {
- super.onNeutral(dialog);
- }
- });
- builder.forceStacking(true);
- MaterialDialog dialog = builder.show();
- if(!IntentUtils.isCallable(context.getApplicationContext(), playStoreIntent)) {
- View pos = dialog.getActionButton(DialogAction.POSITIVE);
- pos.setEnabled(false);
- }
- if (Build.VERSION.SDK_INT < 16) {
- View pos = dialog.getActionButton(DialogAction.NEGATIVE);
- pos.setEnabled(false);
- }
- }
-
- private static void showSpeedSelectorDialog(final Context context) {
- final String[] speedValues = context.getResources().getStringArray(
- R.array.playback_speed_values);
- // According to Java spec these get initialized to false on creation
- final boolean[] speedChecked = new boolean[speedValues.length];
-
- // Build the "isChecked" array so that multiChoice dialog is
- // populated correctly
- List<String> selectedSpeedList = Arrays.asList(UserPreferences
- .getPlaybackSpeedArray());
- for (int i = 0; i < speedValues.length; i++) {
- speedChecked[i] = selectedSpeedList.contains(speedValues[i]);
- }
-
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.set_playback_speed_label);
- builder.setMultiChoiceItems(R.array.playback_speed_values,
- speedChecked, (dialog, which, isChecked) -> {
- speedChecked[which] = isChecked;
- });
- builder.setNegativeButton(android.R.string.cancel, null);
- builder.setPositiveButton(android.R.string.ok,
- (dialog, which) -> {
- int choiceCount = 0;
- for (int i = 0; i < speedChecked.length; i++) {
- if (speedChecked[i]) {
- choiceCount++;
- }
- }
- String[] newSpeedValues = new String[choiceCount];
- int newSpeedIndex = 0;
- for (int i = 0; i < speedChecked.length; i++) {
- if (speedChecked[i]) {
- newSpeedValues[newSpeedIndex++] = speedValues[i];
- }
- }
-
- UserPreferences.setPlaybackSpeedArray(newSpeedValues);
-
- });
- builder.create().show();
- }
+ private static final String TAG = VariableSpeedDialog.class.getSimpleName();
+
+ private static final Intent playStoreIntent = new Intent(Intent.ACTION_VIEW,
+ Uri.parse("market://details?id=com.falconware.prestissimo"));
+
+ private VariableSpeedDialog() {
+ }
+
+ public static void showDialog(final Context context) {
+ if (org.antennapod.audio.MediaPlayer.isPrestoLibraryInstalled(context)
+ || UserPreferences.useSonic()
+ || Build.VERSION.SDK_INT >= 23) {
+ showSpeedSelectorDialog(context);
+ } else {
+ showGetPluginDialog(context, true);
+ }
+ }
+
+ public static void showGetPluginDialog(final Context context) {
+ showGetPluginDialog(context, false);
+ }
+
+ private static void showGetPluginDialog(final Context context, boolean showSpeedSelector) {
+ MaterialDialog.Builder builder = new MaterialDialog.Builder(context);
+ builder.title(R.string.no_playback_plugin_title);
+ builder.content(R.string.no_playback_plugin_or_sonic_msg);
+ builder.positiveText(R.string.enable_sonic);
+ builder.negativeText(R.string.download_plugin_label);
+ builder.neutralText(R.string.close_label);
+ builder.onPositive((dialog, which) -> {
+ if (Build.VERSION.SDK_INT >= 16) { // just to be safe
+ UserPreferences.enableSonic(true);
+ if(showSpeedSelector) {
+ showSpeedSelectorDialog(context);
+ }
+ }
+ });
+ builder.onNegative((dialog, which) -> {
+ try {
+ context.startActivity(playStoreIntent);
+ } catch (ActivityNotFoundException e) {
+ // this is usually thrown on an emulator if the Android market is not installed
+ Log.e(TAG, Log.getStackTraceString(e));
+ }
+ });
+ builder.forceStacking(true);
+ MaterialDialog dialog = builder.show();
+ if (Build.VERSION.SDK_INT < 16) {
+ View pos = dialog.getActionButton(DialogAction.POSITIVE);
+ pos.setEnabled(false);
+ }
+ if(!IntentUtils.isCallable(context.getApplicationContext(), playStoreIntent)) {
+ View pos = dialog.getActionButton(DialogAction.NEGATIVE);
+ pos.setEnabled(false);
+ }
+ }
+
+ private static void showSpeedSelectorDialog(final Context context) {
+ final String[] speedValues = context.getResources().getStringArray(
+ R.array.playback_speed_values);
+ // According to Java spec these get initialized to false on creation
+ final boolean[] speedChecked = new boolean[speedValues.length];
+
+ // Build the "isChecked" array so that multiChoice dialog is
+ // populated correctly
+ List<String> selectedSpeedList = Arrays.asList(UserPreferences
+ .getPlaybackSpeedArray());
+ for (int i = 0; i < speedValues.length; i++) {
+ speedChecked[i] = selectedSpeedList.contains(speedValues[i]);
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(R.string.set_playback_speed_label);
+ builder.setMultiChoiceItems(R.array.playback_speed_values,
+ speedChecked, (dialog, which, isChecked) -> {
+ speedChecked[which] = isChecked;
+ });
+ builder.setNegativeButton(android.R.string.cancel, null);
+ builder.setPositiveButton(android.R.string.ok,
+ (dialog, which) -> {
+ int choiceCount = 0;
+ for (int i = 0; i < speedChecked.length; i++) {
+ if (speedChecked[i]) {
+ choiceCount++;
+ }
+ }
+ String[] newSpeedValues = new String[choiceCount];
+ int newSpeedIndex = 0;
+ for (int i = 0; i < speedChecked.length; i++) {
+ if (speedChecked[i]) {
+ newSpeedValues[newSpeedIndex++] = speedValues[i];
+ }
+ }
+
+ UserPreferences.setPlaybackSpeedArray(newSpeedValues);
+
+ });
+ builder.create().show();
+ }
}
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 2bc4e9ded..273c75240 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -46,6 +46,7 @@ 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.core.util.LongList;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.greenrobot.event.EventBus;
@@ -382,6 +383,34 @@ public class AllEpisodesFragment extends Fragment {
}
return false;
}
+
+ @Override
+ public LongList getQueueIds() {
+ LongList queueIds = new LongList();
+ if(episodes == null) {
+ return queueIds;
+ }
+ for(FeedItem item : episodes) {
+ if(item.isTagged(FeedItem.TAG_QUEUE)) {
+ queueIds.add(item.getId());
+ }
+ }
+ return queueIds;
+ }
+
+ @Override
+ public LongList getFavoritesIds() {
+ LongList favoritesIds = new LongList();
+ if(episodes == null) {
+ return favoritesIds;
+ }
+ for(FeedItem item : episodes) {
+ if(item.isTagged(FeedItem.TAG_FAVORITE)) {
+ favoritesIds.add(item.getId());
+ }
+ }
+ return favoritesIds;
+ }
};
public void onEventMainThread(FeedItemEvent event) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
new file mode 100644
index 000000000..96abdd835
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
@@ -0,0 +1,77 @@
+package de.danoeh.antennapod.fragment;
+
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.view.View;
+import android.widget.ListView;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.AudioplayerActivity.AudioplayerContentFragment;
+import de.danoeh.antennapod.adapter.ChaptersListAdapter;
+import de.danoeh.antennapod.core.feed.Chapter;
+import de.danoeh.antennapod.core.util.playback.Playable;
+import de.danoeh.antennapod.core.util.playback.PlaybackController;
+
+
+public class ChaptersFragment extends ListFragment implements AudioplayerContentFragment {
+
+ private Playable media;
+ private PlaybackController controller;
+
+ private ChaptersListAdapter adapter;
+
+ public static ChaptersFragment newInstance(Playable media, PlaybackController controller) {
+ ChaptersFragment f = new ChaptersFragment();
+ f.media = media;
+ f.controller = controller;
+ return f;
+ }
+
+ @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);
+
+ adapter = new ChaptersListAdapter(getActivity(), 0, pos -> {
+ Chapter chapter = (Chapter) getListAdapter().getItem(pos);
+ controller.seekToChapter(chapter);
+ });
+ setListAdapter(adapter);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ adapter.setMedia(media);
+ adapter.notifyDataSetChanged();
+ if(media == null || media.getChapters() == null) {
+ setEmptyText(getString(R.string.no_chapters_label));
+ } else {
+ setEmptyText(null);
+ }
+ }
+
+ public void onDestroy() {
+ super.onDestroy();
+ adapter = null;
+ }
+
+ @Override
+ public void onMediaChanged(Playable media) {
+ if(this.media == media || adapter == null) {
+ return;
+ }
+ this.media = media;
+ adapter.setMedia(media);
+ adapter.notifyDataSetChanged();
+ if(media == null || media.getChapters() == null || media.getChapters().size() == 0) {
+ setEmptyText(getString(R.string.no_items_label));
+ } else {
+ setEmptyText(null);
+ }
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
index a1667cce0..931d14924 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
@@ -1,7 +1,5 @@
package de.danoeh.antennapod.fragment;
-import android.app.Activity;
-import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
@@ -9,13 +7,11 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
+import android.widget.TextView;
import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
-import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.AudioplayerActivity;
import de.danoeh.antennapod.activity.AudioplayerActivity.AudioplayerContentFragment;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.util.playback.Playable;
@@ -23,17 +19,18 @@ import de.danoeh.antennapod.core.util.playback.Playable;
/**
* Displays the cover and the title of a FeedItem.
*/
-public class CoverFragment extends Fragment implements
- AudioplayerContentFragment {
+public class CoverFragment extends Fragment implements AudioplayerContentFragment {
+
private static final String TAG = "CoverFragment";
private static final String ARG_PLAYABLE = "arg.playable";
private Playable media;
+ private View root;
+ private TextView txtvPodcastTitle;
+ private TextView txtvEpisodeTitle;
private ImageView imgvCover;
- private boolean viewCreated = false;
-
public static CoverFragment newInstance(Playable item) {
CoverFragment f = new CoverFragment();
if (item != null) {
@@ -47,7 +44,6 @@ public class CoverFragment extends Fragment implements
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setRetainInstance(true);
Bundle args = getArguments();
if (args != null) {
media = args.getParcelable(ARG_PLAYABLE);
@@ -59,39 +55,28 @@ public class CoverFragment extends Fragment implements
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- View root = inflater.inflate(R.layout.cover_fragment, container, false);
+ root = inflater.inflate(R.layout.cover_fragment, container, false);
+ txtvPodcastTitle = (TextView) root.findViewById(R.id.txtvPodcastTitle);
+ txtvEpisodeTitle = (TextView) root.findViewById(R.id.txtvEpisodeTitle);
imgvCover = (ImageView) root.findViewById(R.id.imgvCover);
- imgvCover.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Activity activity = getActivity();
- if (activity != null && activity instanceof AudioplayerActivity) {
- ((AudioplayerActivity)activity).switchToLastFragment();
- }
- }
- });
- viewCreated = true;
return root;
}
private void loadMediaInfo() {
+ if(imgvCover == null) {
+ return;
+ }
if (media != null) {
- imgvCover.post(new Runnable() {
-
- @Override
- public void run() {
- Context c = getActivity();
- if (c != null) {
- Glide.with(c)
- .load(media.getImageUri())
- .placeholder(R.color.light_gray)
- .error(R.color.light_gray)
- .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
- .dontAnimate()
- .into(imgvCover);
- }
- }
- });
+ Log.d(TAG, "feed title: " + media.getFeedTitle());
+ Log.d(TAG, "episode title: " + media.getEpisodeTitle());
+ txtvPodcastTitle.setText(media.getFeedTitle());
+ txtvEpisodeTitle.setText(media.getEpisodeTitle());
+ Glide.with(this)
+ .load(media.getImageUri())
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .dontAnimate()
+ .fitCenter()
+ .into(imgvCover);
} else {
Log.w(TAG, "loadMediaInfo was called while media was null");
}
@@ -99,12 +84,10 @@ public class CoverFragment extends Fragment implements
@Override
public void onStart() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "On Start");
+ Log.d(TAG, "On Start");
super.onStart();
if (media != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading media info");
+ Log.d(TAG, "Loading media info");
loadMediaInfo();
} else {
Log.w(TAG, "Unable to load media info: media was null");
@@ -112,12 +95,19 @@ public class CoverFragment extends Fragment implements
}
@Override
- public void onDataSetChanged(Playable media) {
- this.media = media;
- if (viewCreated) {
- loadMediaInfo();
- }
+ public void onDestroy() {
+ super.onDestroy();
+ // prevent memory leaks
+ root = null;
+ }
+ @Override
+ public void onMediaChanged(Playable media) {
+ if(this.media == media) {
+ return;
+ }
+ this.media = media;
+ loadMediaInfo();
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
index 888684313..80a9bf0b3 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
@@ -13,7 +13,6 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
@@ -80,50 +79,15 @@ public class ExternalPlayerFragment extends Fragment {
return new PlaybackController(getActivity(), true) {
@Override
- public void setupGUI() {
- }
-
- @Override
public void onPositionObserverUpdate() {
ExternalPlayerFragment.this.onPositionObserverUpdate();
}
@Override
- public void onReloadNotification(int code) {
- }
-
- @Override
- public void onBufferStart() {
- }
-
- @Override
- public void onBufferEnd() {
- }
-
- @Override
- public void onBufferUpdate(float progress) {
- }
-
- @Override
- public void onSleepTimerUpdate() {
- }
-
- @Override
- public void handleError(int code) {
- }
-
- @Override
public ImageButton getPlayButton() {
return butPlay;
}
- @Override
- public void postStatusMsg(int msg) {
- }
-
- @Override
- public void clearStatusMsg() {
- }
@Override
public boolean loadMediaInfo() {
@@ -136,14 +100,6 @@ public class ExternalPlayerFragment extends Fragment {
}
@Override
- public void onAwaitingVideoSurface() {
- }
-
- @Override
- public void onServiceQueried() {
- }
-
- @Override
public void onShutdownNotification() {
playbackDone();
}
@@ -152,10 +108,6 @@ public class ExternalPlayerFragment extends Fragment {
public void onPlaybackEnd() {
playbackDone();
}
-
- @Override
- public void onPlaybackSpeedChange() {
- }
};
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
index faa4413bb..4c723e5ff 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
@@ -7,8 +7,9 @@ import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.res.TypedArray;
+import android.graphics.Color;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
@@ -20,12 +21,14 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.webkit.WebSettings.LayoutAlgorithm;
+import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.AudioplayerActivity;
+import de.danoeh.antennapod.activity.AudioplayerActivity.AudioplayerContentFragment;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
@@ -36,11 +39,15 @@ import de.danoeh.antennapod.core.util.ShownotesProvider;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.core.util.playback.Timeline;
+import rx.Observable;
+import rx.Subscription;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
/**
* Displays the description of a Playable object in a Webview.
*/
-public class ItemDescriptionFragment extends Fragment {
+public class ItemDescriptionFragment extends Fragment implements AudioplayerContentFragment {
private static final String TAG = "ItemDescriptionFragment";
@@ -55,12 +62,12 @@ public class ItemDescriptionFragment extends Fragment {
private static final String ARG_HIGHLIGHT_TIMECODES = "arg.highlightTimecodes";
private WebView webvDescription;
+ private String webvData;
private ShownotesProvider shownotesProvider;
private Playable media;
-
- private AsyncTask<Void, Void, Void> webViewLoader;
+ private Subscription webViewLoader;
/**
* URL that was selected via long-press.
@@ -106,17 +113,17 @@ public class ItemDescriptionFragment extends Fragment {
Bundle savedInstanceState) {
Log.d(TAG, "Creating view");
webvDescription = new WebView(getActivity());
- if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
- if (Build.VERSION.SDK_INT >= 11
- && Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
- webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
- }
- webvDescription.setBackgroundColor(getResources().getColor(
- R.color.black));
+ if (Build.VERSION.SDK_INT >= 11) {
+ webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
+ TypedArray ta = getActivity().getTheme().obtainStyledAttributes(new int[]
+ {android.R.attr.colorBackground});
+ int backgroundColor = ta.getColor(0, UserPreferences.getTheme() ==
+ R.style.Theme_AntennaPod_Dark ? Color.BLACK : Color.WHITE);
+ ta.recycle();
+ webvDescription.setBackgroundColor(backgroundColor);
webvDescription.getSettings().setUseWideViewPort(false);
- webvDescription.getSettings().setLayoutAlgorithm(
- LayoutAlgorithm.NARROW_COLUMNS);
+ webvDescription.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
webvDescription.getSettings().setLoadWithOverviewMode(true);
webvDescription.setOnLongClickListener(webViewLongClickListener);
webvDescription.setWebViewClient(new WebViewClient() {
@@ -142,14 +149,7 @@ public class ItemDescriptionFragment extends Fragment {
super.onPageFinished(view, url);
Log.d(TAG, "Page finished");
// Restoring the scroll position might not always work
- view.postDelayed(new Runnable() {
-
- @Override
- public void run() {
- restoreFromPreference();
- }
-
- }, 50);
+ view.postDelayed(() -> restoreFromPreference(), 50);
}
});
@@ -159,26 +159,11 @@ public class ItemDescriptionFragment extends Fragment {
}
@Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- Log.d(TAG, "Fragment attached");
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- Log.d(TAG, "Fragment detached");
- if (webViewLoader != null) {
- webViewLoader.cancel(true);
- }
- }
-
- @Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Fragment destroyed");
if (webViewLoader != null) {
- webViewLoader.cancel(true);
+ webViewLoader.unsubscribe();
}
if (webvDescription != null) {
webvDescription.removeAllViews();
@@ -194,7 +179,6 @@ public class ItemDescriptionFragment extends Fragment {
Bundle args = getArguments();
saveState = args.getBoolean(ARG_SAVE_STATE, false);
highlightTimecodes = args.getBoolean(ARG_HIGHLIGHT_TIMECODES, false);
-
}
@Override
@@ -204,46 +188,21 @@ public class ItemDescriptionFragment extends Fragment {
if (args.containsKey(ARG_PLAYABLE)) {
media = args.getParcelable(ARG_PLAYABLE);
shownotesProvider = media;
- startLoader();
+ load();
} else if (args.containsKey(ARG_FEEDITEM_ID)) {
- AsyncTask<Void, Void, FeedItem> itemLoadTask = new AsyncTask<Void, Void, FeedItem>() {
-
- @Override
- protected FeedItem doInBackground(Void... voids) {
- return DBReader.getFeedItem(getArguments().getLong(ARG_FEEDITEM_ID));
- }
-
- @Override
- protected void onPostExecute(FeedItem feedItem) {
- super.onPostExecute(feedItem);
- shownotesProvider = feedItem;
- startLoader();
- }
- };
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- itemLoadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- itemLoadTask.execute();
- }
+ long id = getArguments().getLong(ARG_FEEDITEM_ID);
+ Observable.defer(() -> Observable.just(DBReader.getFeedItem(id)))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(feedItem -> {
+ shownotesProvider = feedItem;
+ load();
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ });
}
-
-
- }
-
- @Override
- public void onResume() {
- super.onResume();
}
- @SuppressLint("NewApi")
- private void startLoader() {
- webViewLoader = createLoader();
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- webViewLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- webViewLoader.execute();
- }
- }
private View.OnLongClickListener webViewLongClickListener = new View.OnLongClickListener() {
@@ -338,49 +297,31 @@ public class ItemDescriptionFragment extends Fragment {
}
}
- private AsyncTask<Void, Void, Void> createLoader() {
- return new AsyncTask<Void, Void, Void>() {
- @Override
- protected void onCancelled() {
- super.onCancelled();
- webViewLoader = null;
- }
-
- String data;
-
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- // /webvDescription.loadData(url, "text/html", "utf-8");
- webvDescription.loadDataWithBaseURL(null, data, "text/html",
- "utf-8", "about:blank");
- Log.d(TAG, "Webview loaded");
- webViewLoader = null;
- }
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- Log.d(TAG, "Loading Webview");
- try {
- Activity activity = getActivity();
- if (activity != null) {
- Timeline timeline = new Timeline(activity, shownotesProvider);
- data = timeline.processShownotes(highlightTimecodes);
- } else {
- cancel(true);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
+ private void load() {
+ Log.d(TAG, "load()");
+ if(webViewLoader != null) {
+ webViewLoader.unsubscribe();
+ }
+ if(shownotesProvider == null) {
+ return;
+ }
+ webViewLoader = Observable.defer(() -> Observable.just(loadData()))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(data -> {
+ webvData = data;
+ webvDescription.loadDataWithBaseURL(null, data, "text/html",
+ "utf-8", "about:blank");
+ Log.d(TAG, "Webview loaded");
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ });
+ }
- };
+ private String loadData() {
+ Timeline timeline = new Timeline(getActivity(), shownotesProvider);
+ String data = timeline.processShownotes(highlightTimecodes);
+ return data;
}
@Override
@@ -410,7 +351,7 @@ public class ItemDescriptionFragment extends Fragment {
}
private boolean restoreFromPreference() {
- if (saveState) {
+ if (!saveState) {
Log.d(TAG, "Restoring from preferences");
Activity activity = getActivity();
if (activity != null) {
@@ -433,15 +374,22 @@ public class ItemDescriptionFragment extends Fragment {
private void onTimecodeLinkSelected(String link) {
int time = Timeline.getTimecodeLinkTime(link);
- if (getActivity() != null && getActivity() instanceof ItemDescriptionFragmentCallback) {
- PlaybackController pc = ((ItemDescriptionFragmentCallback) getActivity()).getPlaybackController();
+ if (getActivity() != null && getActivity() instanceof AudioplayerActivity) {
+ PlaybackController pc = ((AudioplayerActivity) getActivity()).getPlaybackController();
if (pc != null) {
pc.seekTo(time);
}
}
}
- public interface ItemDescriptionFragmentCallback {
- public PlaybackController getPlaybackController();
+ @Override
+ public void onMediaChanged(Playable media) {
+ if(this.media == media) {
+ return;
+ }
+ this.media = media;
+ this.shownotesProvider = media;
+ load();
}
+
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
index 21268815a..ce80dc827 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
@@ -9,7 +9,6 @@ import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
-import android.support.v4.util.Pair;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
@@ -40,6 +39,7 @@ import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
+import de.danoeh.antennapod.core.event.FavoritesEvent;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
@@ -95,6 +95,7 @@ public class ItemFragment extends Fragment {
private long itemID;
private FeedItem item;
private LongList queue;
+ private LongList favorites;
private String webviewData;
private List<Downloader> downloaderList;
@@ -249,10 +250,10 @@ public class ItemFragment extends Fragment {
inflater.inflate(R.menu.feeditem_options, menu);
popupMenu = menu;
if (item.hasMedia()) {
- FeedItemMenuHandler.onPrepareMenu(getActivity(), popupMenuInterface, item, true, queue);
+ FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, queue, favorites);
} else {
// these are already available via button1 and button2
- FeedItemMenuHandler.onPrepareMenu(getActivity(), popupMenuInterface, item, true, queue,
+ FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, queue, favorites,
R.id.mark_read_item, R.id.visit_website_item);
}
}
@@ -310,7 +311,7 @@ public class ItemFragment extends Fragment {
.dontAnimate()
.into(imgvCover);
- progbarDownload.setVisibility(View.INVISIBLE);
+ progbarDownload.setVisibility(View.GONE);
if (item.hasMedia() && downloaderList != null) {
for (Downloader downloader : downloaderList) {
if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
@@ -332,7 +333,7 @@ public class ItemFragment extends Fragment {
butAction1Text = R.string.mark_read_label;
}
if (item.getLink() != null) {
- butAction2Icon = "{ma-web 24sp}";
+ butAction2Icon = "{md-web 24sp}";
butAction2Text = R.string.visit_website_label;
}
} else {
@@ -457,6 +458,12 @@ public class ItemFragment extends Fragment {
}
}
+ public void onEventMainThread(FavoritesEvent event) {
+ if(event.item.getId() == itemID) {
+ load();
+ }
+ }
+
public void onEventMainThread(FeedItemEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
for(FeedItem item : event.items) {
@@ -500,8 +507,9 @@ public class ItemFragment extends Fragment {
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
- item = result.first;
- queue = result.second;
+ item = (FeedItem) result[0];
+ queue = (LongList) result[1];
+ favorites = (LongList) result[2];
if (!itemsLoaded) {
itemsLoaded = true;
onFragmentLoaded();
@@ -513,14 +521,25 @@ public class ItemFragment extends Fragment {
});
}
- private Pair<FeedItem,LongList> loadInBackground() {
- FeedItem data1 = DBReader.getFeedItem(itemID);
- if (data1 != null) {
- Timeline t = new Timeline(getActivity(), data1);
+ private Object[] loadInBackground() {
+ FeedItem feedItem = DBReader.getFeedItem(itemID);
+ if (feedItem != null) {
+ Timeline t = new Timeline(getActivity(), feedItem);
webviewData = t.processShownotes(false);
}
- LongList data2 = DBReader.getQueueIDList();
- return Pair.create(data1, data2);
+ LongList queue;
+ if(feedItem.isTagged(FeedItem.TAG_QUEUE)) {
+ queue = LongList.of(feedItem.getId());
+ } else {
+ queue = new LongList(0);
+ }
+ LongList favorites;
+ if(feedItem.isTagged(FeedItem.TAG_FAVORITE)) {
+ favorites = LongList.of(feedItem.getId());
+ } else {
+ favorites = new LongList(0);
+ }
+ return new Object[] { feedItem, queue, favorites };
}
}
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 97c446fab..7a9b73982 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
@@ -10,7 +10,6 @@ import android.graphics.LightingColorFilter;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
-import android.support.v4.util.Pair;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.SearchView;
import android.util.Log;
@@ -48,6 +47,7 @@ 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.FavoritesEvent;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
@@ -99,6 +99,7 @@ public class ItemlistFragment extends ListFragment {
private long feedID;
private Feed feed;
private LongList queuedItemsIds;
+ private LongList favoritedItemsId;
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
@@ -324,7 +325,8 @@ public class ItemlistFragment extends ListFragment {
contextMenu = menu;
lastMenuInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
- FeedItemMenuHandler.onPrepareMenu(getActivity(), contextMenuInterface, item, true, queuedItemsIds);
+ FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, queuedItemsIds,
+ favoritedItemsId);
}
@Override
@@ -389,6 +391,11 @@ public class ItemlistFragment extends ListFragment {
loadItems();
}
+ public void onEvent(FavoritesEvent event) {
+ Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
+ loadItems();
+ }
+
public void onEvent(FeedEvent event) {
Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
if(event.feedId == feedID) {
@@ -626,8 +633,9 @@ public class ItemlistFragment extends ListFragment {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
if (result != null) {
- feed = result.first;
- queuedItemsIds = result.second;
+ feed = (Feed) result[0];
+ queuedItemsIds = (LongList) result[1];
+ favoritedItemsId = (LongList) result[2];
itemsLoaded = true;
if (viewsCreated) {
onFragmentLoaded();
@@ -638,14 +646,15 @@ public class ItemlistFragment extends ListFragment {
});
}
- private Pair<Feed, LongList> loadData() {
+ private Object[] loadData() {
Feed feed = DBReader.getFeed(feedID);
if(feed != null && feed.getItemFilter() != null) {
FeedItemFilter filter = feed.getItemFilter();
feed.setItems(filter.filter(feed.getItems()));
}
LongList queuedItemsIds = DBReader.getQueueIDList();
- return Pair.create(feed, queuedItemsIds);
+ LongList favoritedItemsId = DBReader.getFavoriteIDList();
+ return new Object[] { feed, queuedItemsIds, favoritedItemsId };
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
index e92df4885..eb947dc2b 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
@@ -1,17 +1,23 @@
package de.danoeh.antennapod.fragment;
import android.content.Intent;
-import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.Fragment;
+import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
+import android.widget.Button;
import android.widget.GridView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import com.afollestad.materialdialogs.MaterialDialog;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
@@ -25,13 +31,14 @@ import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
import de.danoeh.antennapod.adapter.itunes.ItunesAdapter;
import de.danoeh.antennapod.core.ClientConfig;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
+import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
@@ -46,21 +53,22 @@ public class ItunesSearchFragment extends Fragment {
private static final String API_URL = "https://itunes.apple.com/search?media=podcast&term=%s";
- /**
- * Search input field
- */
- private SearchView searchView;
/**
* Adapter responsible with the search results
*/
private ItunesAdapter adapter;
+ private GridView gridView;
+ private ProgressBar progressBar;
+ private TextView txtvError;
+ private Button butRetry;
+ private TextView txtvEmpty;
/**
* List of podcasts retreived from the search
*/
private List<Podcast> searchResults;
-
+ private List<Podcast> topList;
private Subscription subscription;
/**
@@ -70,13 +78,17 @@ public class ItunesSearchFragment extends Fragment {
void updateData(List<Podcast> result) {
this.searchResults = result;
adapter.clear();
-
- //ArrayAdapter.addAll() requires minsdk > 10
- for(Podcast p: result) {
- adapter.add(p);
+ if (result != null && result.size() > 0) {
+ gridView.setVisibility(View.VISIBLE);
+ txtvEmpty.setVisibility(View.GONE);
+ for (Podcast p : result) {
+ adapter.add(p);
+ }
+ adapter.notifyDataSetInvalidated();
+ } else {
+ gridView.setVisibility(View.GONE);
+ txtvEmpty.setVisibility(View.VISIBLE);
}
-
- adapter.notifyDataSetInvalidated();
}
/**
@@ -89,47 +101,105 @@ public class ItunesSearchFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- adapter = new ItunesAdapter(getActivity(), new ArrayList<Podcast>());
-
+ setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
- View view = inflater.inflate(R.layout.fragment_itunes_search, container, false);
- GridView gridView = (GridView) view.findViewById(R.id.gridView);
+ View root = inflater.inflate(R.layout.fragment_itunes_search, container, false);
+ gridView = (GridView) root.findViewById(R.id.gridView);
+ adapter = new ItunesAdapter(getActivity(), new ArrayList<>());
gridView.setAdapter(adapter);
//Show information about the podcast when the list item is clicked
- gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Intent intent = new Intent(getActivity(),
- OnlineFeedViewActivity.class);
-
- //Tell the OnlineFeedViewActivity where to go
- String url = searchResults.get(position).feedUrl;
- intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, url);
-
+ gridView.setOnItemClickListener((parent, view1, position, id) -> {
+ Podcast podcast = searchResults.get(position);
+ if (!podcast.feedUrl.contains("itunes.apple.com")) {
+ Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);
+ intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, podcast.feedUrl);
intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, "iTunes");
startActivity(intent);
+ } else {
+ gridView.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
+ rx.Observable.create((Observable.OnSubscribe<String>) subscriber -> {
+ OkHttpClient client = AntennapodHttpClient.getHttpClient();
+ Request.Builder httpReq = new Request.Builder()
+ .url(podcast.feedUrl)
+ .header("User-Agent", ClientConfig.USER_AGENT);
+ try {
+ Response response = client.newCall(httpReq.build()).execute();
+ if (response.isSuccessful()) {
+ String resultString = response.body().string();
+ JSONObject result = new JSONObject(resultString);
+ JSONObject results = result.getJSONArray("results").getJSONObject(0);
+ String feedUrl = results.getString("feedUrl");
+ subscriber.onNext(feedUrl);
+ } else {
+ String prefix = getString(R.string.error_msg_prefix);
+ subscriber.onError(new IOException(prefix + response));
+ }
+ } catch (IOException | JSONException e) {
+ subscriber.onError(e);
+ }
+ subscriber.onCompleted();
+ })
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(feedUrl -> {
+ progressBar.setVisibility(View.GONE);
+ gridView.setVisibility(View.VISIBLE);
+ Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);
+ intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, feedUrl);
+ intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, "iTunes");
+ startActivity(intent);
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ progressBar.setVisibility(View.GONE);
+ gridView.setVisibility(View.VISIBLE);
+ String prefix = getString(R.string.error_msg_prefix);
+ new MaterialDialog.Builder(getActivity())
+ .content(prefix + " " + error.getMessage())
+ .neutralText(android.R.string.ok)
+ .show();
+ });
}
});
+ progressBar = (ProgressBar) root.findViewById(R.id.progressBar);
+ txtvError = (TextView) root.findViewById(R.id.txtvError);
+ butRetry = (Button) root.findViewById(R.id.butRetry);
+ txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
+
+ loadToplist();
+
+ return root;
+ }
- //Configure search input view to be expanded by default with a visible submit button
- searchView = (SearchView) view.findViewById(R.id.itunes_search_view);
- searchView.setIconifiedByDefault(false);
- searchView.setIconified(false);
- searchView.setSubmitButtonEnabled(true);
- searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (subscription != null) {
+ subscription.unsubscribe();
+ }
+ adapter = null;
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.itunes_search, menu);
+ MenuItem searchItem = menu.findItem(R.id.action_search);
+ final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
+ MenuItemUtils.adjustTextColor(getActivity(), sv);
+ sv.setQueryHint(getString(R.string.search_itunes_label));
+ sv.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
- //This prevents onQueryTextSubmit() from being called twice when keyboard is used
- //to submit the query.
- searchView.clearFocus();
+ sv.clearFocus();
search(s);
- return false;
+ return true;
}
@Override
@@ -137,21 +207,97 @@ public class ItunesSearchFragment extends Fragment {
return false;
}
});
+ MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ return true;
+ }
- SearchView.SearchAutoComplete textField = (SearchView.SearchAutoComplete) searchView.findViewById(de.danoeh.antennapod.R.id.search_src_text);
- if(UserPreferences.getTheme() == de.danoeh.antennapod.R.style.Theme_AntennaPod_Dark) {
- textField.setTextColor(Resources.getSystem().getColor(android.R.color.white));
- } else {
- textField.setTextColor(Resources.getSystem().getColor(android.R.color.black));
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ if(searchResults != null) {
+ searchResults = null;
+ updateData(topList);
+ }
+ return true;
+ }
+ });
+ }
+
+ private void loadToplist() {
+ if (subscription != null) {
+ subscription.unsubscribe();
}
+ gridView.setVisibility(View.GONE);
+ txtvError.setVisibility(View.GONE);
+ butRetry.setVisibility(View.GONE);
+ txtvEmpty.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
+ subscription = rx.Observable.create((Observable.OnSubscribe<List<Podcast>>) subscriber -> {
+ String lang = Locale.getDefault().getLanguage();
+ String url = "https://itunes.apple.com/" + lang + "/rss/toppodcasts/limit=25/explicit=true/json";
+ OkHttpClient client = AntennapodHttpClient.getHttpClient();
+ Request.Builder httpReq = new Request.Builder()
+ .url(url)
+ .header("User-Agent", ClientConfig.USER_AGENT);
+ List<Podcast> results = new ArrayList<>();
+ try {
+ Response response = client.newCall(httpReq.build()).execute();
+ if(!response.isSuccessful()) {
+ // toplist for language does not exist, fall back to united states
+ url = "https://itunes.apple.com/us/rss/toppodcasts/limit=25/explicit=true/json";
+ httpReq = new Request.Builder()
+ .url(url)
+ .header("User-Agent", ClientConfig.USER_AGENT);
+ response = client.newCall(httpReq.build()).execute();
+ }
+ if(response.isSuccessful()) {
+ String resultString = response.body().string();
+ JSONObject result = new JSONObject(resultString);
+ JSONObject feed = result.getJSONObject("feed");
+ JSONArray entries = feed.getJSONArray("entry");
- return view;
+ for(int i=0; i < entries.length(); i++) {
+ JSONObject json = entries.getJSONObject(i);
+ Podcast podcast = Podcast.fromToplist(json);
+ results.add(podcast);
+ }
+ }
+ else {
+ String prefix = getString(R.string.error_msg_prefix);
+ subscriber.onError(new IOException(prefix + response));
+ }
+ } catch (IOException | JSONException e) {
+ subscriber.onError(e);
+ }
+ subscriber.onNext(results);
+ subscriber.onCompleted();
+ })
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(podcasts -> {
+ progressBar.setVisibility(View.GONE);
+ topList = podcasts;
+ updateData(topList);
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ progressBar.setVisibility(View.GONE);
+ txtvError.setText(error.toString());
+ txtvError.setVisibility(View.VISIBLE);
+ butRetry.setOnClickListener(v -> loadToplist());
+ butRetry.setVisibility(View.VISIBLE);
+ });
}
private void search(String query) {
if (subscription != null) {
subscription.unsubscribe();
}
+ gridView.setVisibility(View.GONE);
+ txtvError.setVisibility(View.GONE);
+ butRetry.setVisibility(View.GONE);
+ txtvEmpty.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
subscription = rx.Observable.create((Observable.OnSubscribe<List<Podcast>>) subscriber -> {
String encodedQuery = null;
try {
@@ -181,15 +327,16 @@ public class ItunesSearchFragment extends Fragment {
for (int i = 0; i < j.length(); i++) {
JSONObject podcastJson = j.getJSONObject(i);
- Podcast podcast = new Podcast(podcastJson);
+ Podcast podcast = Podcast.fromSearch(podcastJson);
podcasts.add(podcast);
}
}
else {
- subscriber.onError(new IOException("Unexpected error: " + response));
+ String prefix = getString(R.string.error_msg_prefix);
+ subscriber.onError(new IOException(prefix + response));
}
} catch (IOException | JSONException e) {
- Log.e(TAG, Log.getStackTraceString(e));
+ subscriber.onError(e);
}
subscriber.onNext(podcasts);
subscriber.onCompleted();
@@ -197,9 +344,15 @@ public class ItunesSearchFragment extends Fragment {
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(podcasts -> {
+ progressBar.setVisibility(View.GONE);
updateData(podcasts);
}, error -> {
Log.e(TAG, Log.getStackTraceString(error));
+ progressBar.setVisibility(View.GONE);
+ txtvError.setText(error.toString());
+ txtvError.setVisibility(View.VISIBLE);
+ butRetry.setOnClickListener(v -> search(query));
+ butRetry.setVisibility(View.VISIBLE);
});
}
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 2e779bf15..b3f6c3534 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -68,6 +68,7 @@ public class QueueFragment extends Fragment {
public static final String TAG = "QueueFragment";
private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED |
+ EventDistributor.UNREAD_ITEMS_UPDATE | // sent when playback position is reset
EventDistributor.PLAYER_STATUS_UPDATE;
private TextView infoBar;
@@ -567,6 +568,20 @@ public class QueueFragment extends Fragment {
public LongList getQueueIds() {
return queue != null ? LongList.of(FeedItemUtil.getIds(queue)) : new LongList(0);
}
+
+ @Override
+ public LongList getFavoritesIds() {
+ LongList favoritesIds = new LongList();
+ if(queue == null) {
+ return favoritesIds;
+ }
+ for(FeedItem item : queue) {
+ if(item.isTagged(FeedItem.TAG_FAVORITE)) {
+ favoritesIds.add(item.getId());
+ }
+ }
+ return favoritesIds;
+ }
};
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
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 513cf2760..dbd18163c 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
@@ -4,7 +4,7 @@ import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.view.MenuItemCompat;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.Menu;
@@ -116,7 +116,7 @@ public class SearchFragment extends ListFragment {
final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
lv.setPadding(0, vertPadding, 0, vertPadding);
- ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(R.string.search_label);
+ ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(R.string.search_label);
viewCreated = true;
if (itemsLoaded) {
onFragmentLoaded();
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 06dbe4963..58fe8afbf 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
@@ -57,22 +57,25 @@ public class FeedItemMenuHandler {
* @param queueAccess Used for testing if the queue contains the selected item
* @return Returns true if selectedItem is not null.
*/
- public static boolean onPrepareMenu(Context context, MenuInterface mi, FeedItem selectedItem,
- boolean showExtendedMenu, LongList queueAccess) {
+ public static boolean onPrepareMenu(MenuInterface mi,
+ FeedItem selectedItem,
+ boolean showExtendedMenu,
+ LongList queueAccess,
+ LongList favorites) {
if (selectedItem == null) {
return false;
}
boolean hasMedia = selectedItem.getMedia() != null;
- boolean isPlaying = hasMedia
- && selectedItem.getState() == FeedItem.State.PLAYING;
-
- FeedItem.State state = selectedItem.getState();
+ boolean isPlaying = hasMedia && selectedItem.getState() == FeedItem.State.PLAYING;
if (!isPlaying) {
mi.setItemVisibility(R.id.skip_episode_item, false);
}
- boolean isInQueue = selectedItem.isTagged(FeedItem.TAG_QUEUE);
+ boolean isInQueue = false;
+ if(queueAccess != null) {
+ isInQueue = queueAccess.contains(selectedItem.getId());
+ }
if(queueAccess == null || queueAccess.size() == 0 || queueAccess.get(0) == selectedItem.getId()) {
mi.setItemVisibility(R.id.move_to_top_item, false);
}
@@ -123,7 +126,7 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.support_item, false);
}
- boolean isFavorite = selectedItem.isTagged(FeedItem.TAG_FAVORITE);
+ boolean isFavorite = favorites != null && favorites.contains(selectedItem.getId());
mi.setItemVisibility(R.id.add_to_favorites_item, !isFavorite);
mi.setItemVisibility(R.id.remove_from_favorites_item, isFavorite);
@@ -137,9 +140,13 @@ public class FeedItemMenuHandler {
* @param excludeIds Menu item that should be excluded
* @return true if selectedItem is not null.
*/
- public static boolean onPrepareMenu(Context context, MenuInterface mi, FeedItem selectedItem,
- boolean showExtendedMenu, LongList queueAccess, int... excludeIds) {
- boolean rc = onPrepareMenu(context, mi, selectedItem, showExtendedMenu, queueAccess);
+ public static boolean onPrepareMenu(MenuInterface mi,
+ FeedItem selectedItem,
+ boolean showExtendedMenu,
+ LongList queueAccess,
+ LongList favorites,
+ int... excludeIds) {
+ boolean rc = onPrepareMenu(mi, selectedItem, showExtendedMenu, queueAccess, favorites);
if (rc && excludeIds != null) {
for (int id : excludeIds) {
mi.setItemVisibility(id, false);
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 2d6d4cac1..830e9d419 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
@@ -68,8 +68,8 @@ public class FeedMenuHandler {
case R.id.refresh_complete_item:
DBTasks.refreshCompleteFeed(context, selectedFeed);
break;
- case R.id.hide_items:
- showHideDialog(context, selectedFeed);
+ case R.id.filter_items:
+ showFilterDialog(context, selectedFeed);
break;
case R.id.mark_all_read_item:
ConfirmationDialog conDialog = new ConfirmationDialog(context,
@@ -110,14 +110,13 @@ public class FeedMenuHandler {
return true;
}
- private static void showHideDialog(final Context context, final Feed feed) {
-
- final String[] items = context.getResources().getStringArray(R.array.episode_hide_options);
- final String[] values = context.getResources().getStringArray(R.array.episode_hide_values);
+ private static void showFilterDialog(final Context context, final Feed feed) {
+ final String[] items = context.getResources().getStringArray(R.array.episode_filter_options);
+ final String[] values = context.getResources().getStringArray(R.array.episode_filter_values);
final boolean[] checkedItems = new boolean[items.length];
- final Set<String> hidden = new HashSet<String>(Arrays.asList(feed.getItemFilter().getValues()));
- Iterator<String> it = hidden.iterator();
+ final Set<String> filter = new HashSet<>(Arrays.asList(feed.getItemFilter().getValues()));
+ Iterator<String> it = filter.iterator();
while(it.hasNext()) {
// make sure we have no empty strings in the filter list
if(TextUtils.isEmpty(it.next())) {
@@ -126,23 +125,23 @@ public class FeedMenuHandler {
}
for(int i=0; i < values.length; i++) {
String value = values[i];
- if(hidden.contains(value)) {
+ if(filter.contains(value)) {
checkedItems[i] = true;
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.hide_episodes_title);
+ builder.setTitle(R.string.filter);
builder.setMultiChoiceItems(items, checkedItems, (dialog, which, isChecked) -> {
if (isChecked) {
- hidden.add(values[which]);
+ filter.add(values[which]);
} else {
- hidden.remove(values[which]);
+ filter.remove(values[which]);
}
});
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- feed.setHiddenItemProperties(hidden.toArray(new String[hidden.size()]));
- DBWriter.setFeedItemsFilter(feed.getId(), hidden);
+ feed.setItemFilter(filter.toArray(new String[filter.size()]));
+ DBWriter.setFeedItemsFilter(feed.getId(), filter);
});
builder.setNegativeButton(R.string.cancel_label, null);
builder.create().show();
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 083ac5202..785944768 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
@@ -397,12 +397,11 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
ui.findPreference("prefSendCrashReport").setOnPreferenceClickListener(preference -> {
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("text/plain");
- String to[] = { "Martin.Fietz@gmail.com" };
- emailIntent .putExtra(Intent.EXTRA_EMAIL, to);
+ emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"Martin.Fietz@gmail.com"});
+ emailIntent.putExtra(Intent.EXTRA_SUBJECT, "AntennaPod Crash Report");
+ emailIntent.putExtra(Intent.EXTRA_TEXT, "Please describe what you were doing when the app crashed");
// the attachment
- emailIntent .putExtra(Intent.EXTRA_STREAM, Uri.fromFile(CrashReportWriter.getFile()));
- // the mail subject
- emailIntent .putExtra(Intent.EXTRA_SUBJECT, "AntennaPod Crash Report");
+ emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(CrashReportWriter.getFile()));
String intentTitle = ui.getActivity().getString(R.string.send_email);
ui.getActivity().startActivity(Intent.createChooser(emailIntent, intentTitle));
return true;
diff --git a/app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java b/app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java
index d61a189c2..323060f81 100644
--- a/app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java
+++ b/app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java
@@ -128,7 +128,7 @@ public class PlayerWidgetService extends Service {
views.setTextViewText(R.id.txtvTitle, media.getEpisodeTitle());
- String progressString = getProgressString(media);
+ String progressString = getProgressString();
if (progressString != null) {
views.setViewVisibility(R.id.txtvProgress, View.VISIBLE);
views.setTextViewText(R.id.txtvProgress, progressString);
@@ -181,9 +181,9 @@ public class PlayerWidgetService extends Service {
return PendingIntent.getBroadcast(this, 0, startingIntent, 0);
}
- private String getProgressString(Playable media) {
- int position = media.getPosition();
- int duration = media.getDuration();
+ private String getProgressString() {
+ int position = playbackService.getCurrentPosition();
+ int duration = playbackService.getDuration();
if (position > 0 && duration > 0) {
return Converter.getDurationStringLong(position) + " / "
+ Converter.getDurationStringLong(duration);