summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java39
-rw-r--r--app/src/main/AndroidManifest.xml8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/PodcastApp.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java35
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/CoverLoader.java100
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/HorizontalFeedListAdapter.java31
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsRecyclerAdapter.java108
-rw-r--r--app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java57
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java34
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/DiscoveryFragment.java53
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/MenuItemToSortOrderConverter.java40
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java11
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java50
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QuickFeedDiscoveryFragment.java55
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java30
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java49
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java27
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java47
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/ThemePreference.java53
-rw-r--r--app/src/main/java/de/danoeh/antennapod/ui/home/sections/DownloadsSection.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java4
-rw-r--r--app/src/main/res/drawable-nodpi/theme_preview_dark.pngbin0 -> 18079 bytes
-rw-r--r--app/src/main/res/drawable-nodpi/theme_preview_light.pngbin0 -> 17760 bytes
-rw-r--r--app/src/main/res/drawable-nodpi/theme_preview_system.pngbin0 -> 34076 bytes
-rw-r--r--app/src/main/res/layout/cover_fragment.xml1
-rw-r--r--app/src/main/res/layout/edit_tags_dialog.xml12
-rw-r--r--app/src/main/res/layout/subscription_item.xml141
-rw-r--r--app/src/main/res/layout/theme_preference.xml123
-rw-r--r--app/src/main/res/menu/downloads_completed.xml5
-rw-r--r--app/src/main/res/menu/queue.xml83
-rw-r--r--app/src/main/res/menu/sort_menu.xml83
-rw-r--r--app/src/main/res/xml/preferences_user_interface.xml14
34 files changed, 790 insertions, 530 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
index 909b7a5a2..b790bc005 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
@@ -3,32 +3,29 @@ package de.test.antennapod.ui;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
-
import androidx.annotation.StringRes;
import androidx.preference.PreferenceManager;
import androidx.test.espresso.matcher.RootMatchers;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
-
-import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithmFactory;
-import org.awaitility.Awaitility;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
-
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.PreferenceActivity;
-import de.danoeh.antennapod.storage.preferences.UserPreferences;
-import de.danoeh.antennapod.storage.preferences.UserPreferences.EnqueueLocation;
import de.danoeh.antennapod.core.storage.APCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm;
+import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithmFactory;
import de.danoeh.antennapod.core.storage.ExceptFavoriteCleanupAlgorithm;
+import de.danoeh.antennapod.storage.preferences.UserPreferences;
+import de.danoeh.antennapod.storage.preferences.UserPreferences.EnqueueLocation;
import de.test.antennapod.EspressoTestUtils;
+import org.awaitility.Awaitility;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
import static androidx.test.espresso.Espresso.onData;
import static androidx.test.espresso.Espresso.onView;
@@ -78,22 +75,6 @@ public class PreferencesTest {
}
@Test
- public void testSwitchTheme() {
- final UserPreferences.ThemePreference theme = UserPreferences.getTheme();
- int otherThemeText;
- if (theme == UserPreferences.ThemePreference.DARK) {
- otherThemeText = R.string.pref_theme_title_light;
- } else {
- otherThemeText = R.string.pref_theme_title_dark;
- }
- clickPreference(R.string.user_interface_label);
- clickPreference(R.string.pref_set_theme_title);
- onView(withText(otherThemeText)).perform(click());
- Awaitility.await().atMost(1000, MILLISECONDS)
- .until(() -> UserPreferences.getTheme() != theme);
- }
-
- @Test
public void testEnablePersistentPlaybackControls() {
final boolean persistNotify = UserPreferences.isPersistNotify();
clickPreference(R.string.user_interface_label);
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9cce60469..d784e8709 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -126,7 +126,13 @@
<activity
android:name=".activity.DownloadAuthenticationActivity"
android:theme="@style/Theme.AntennaPod.Dark.Translucent"
- android:launchMode="singleInstance"/>
+ android:exported="false"
+ android:launchMode="singleInstance">
+ <intent-filter>
+ <action android:name="de.danoeh.antennapod.intents.DOWNLOAD_AUTH_ACTIVITY" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
<activity
android:name=".activity.PreferenceActivity"
diff --git a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
index 7cbe32e11..942e2cf24 100644
--- a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
+++ b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
@@ -12,7 +12,6 @@ import com.joanzapata.iconify.fonts.MaterialModule;
import de.danoeh.antennapod.activity.SplashActivity;
import de.danoeh.antennapod.config.ApplicationCallbacksImpl;
-import de.danoeh.antennapod.config.DownloadServiceCallbacksImpl;
import de.danoeh.antennapod.core.ApCoreEventBusIndex;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.ClientConfigurator;
@@ -35,7 +34,6 @@ public class PodcastApp extends MultiDexApplication {
super.onCreate();
ClientConfig.USER_AGENT = "AntennaPod/" + BuildConfig.VERSION_NAME;
ClientConfig.applicationCallbacks = new ApplicationCallbacksImpl();
- ClientConfig.downloadServiceCallbacks = new DownloadServiceCallbacksImpl();
Thread.setDefaultUncaughtExceptionHandler(new CrashReportWriter());
RxJavaErrorHandlerSetup.setupRxJavaErrorHandler();
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
index 82b9d3d25..176c3c990 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
@@ -12,10 +12,10 @@ import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.dialog.AuthenticationDialog;
+import de.danoeh.antennapod.ui.appstartintent.DownloadAuthenticationActivityStarter;
import io.reactivex.Completable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
-import org.apache.commons.lang3.Validate;
/**
@@ -23,19 +23,13 @@ import org.apache.commons.lang3.Validate;
* The activity MUST be started with the ARG_DOWNlOAD_REQUEST argument set to a non-null value.
*/
public class DownloadAuthenticationActivity extends AppCompatActivity {
-
- /**
- * The download request object that contains information about the resource that requires a username and a password.
- */
- public static final String ARG_DOWNLOAD_REQUEST = "request";
-
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(ThemeSwitcher.getTranslucentTheme(this));
super.onCreate(savedInstanceState);
- Validate.isTrue(getIntent().hasExtra(ARG_DOWNLOAD_REQUEST), "Download request missing");
- DownloadRequest request = getIntent().getParcelableExtra(ARG_DOWNLOAD_REQUEST);
+ DownloadRequest request = getIntent().getParcelableExtra(
+ DownloadAuthenticationActivityStarter.EXTRA_DOWNLOAD_REQUEST);
new AuthenticationDialog(this, R.string.authentication_label, true, "", "") {
@Override
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 6b2267926..fad586328 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
@@ -76,8 +76,6 @@ public class MainActivity extends CastEnabledActivity {
public static final String PREF_NAME = "MainActivityPrefs";
public static final String PREF_IS_FIRST_LAUNCH = "prefMainActivityIsFirstLaunch";
- public static final String EXTRA_FRAGMENT_TAG = "fragment_tag";
- public static final String EXTRA_FRAGMENT_ARGS = "fragment_args";
public static final String EXTRA_FEED_ID = "fragment_feed_id";
public static final String EXTRA_REFRESH_ON_START = "refresh_on_start";
public static final String EXTRA_STARTED_FROM_SEARCH = "started_from_search";
@@ -441,6 +439,9 @@ public class MainActivity extends CastEnabledActivity {
finish();
startActivity(new Intent(this, MainActivity.class));
}
+ if (UserPreferences.getHiddenDrawerItems().contains(NavDrawerFragment.getLastNavFragment(this))) {
+ loadFragment(UserPreferences.getDefaultPage(), null);
+ }
}
@Override
@@ -511,20 +512,12 @@ public class MainActivity extends CastEnabledActivity {
}
private void handleNavIntent() {
+ Log.d(TAG, "handleNavIntent()");
Intent intent = getIntent();
- if (intent.hasExtra(EXTRA_FEED_ID) || intent.hasExtra(EXTRA_FRAGMENT_TAG) || intent.hasExtra(EXTRA_REFRESH_ON_START)) {
- Log.d(TAG, "handleNavIntent()");
- String tag = intent.getStringExtra(EXTRA_FRAGMENT_TAG);
- Bundle args = intent.getBundleExtra(EXTRA_FRAGMENT_ARGS);
- boolean refreshOnStart = intent.getBooleanExtra(EXTRA_REFRESH_ON_START, false);
- if (refreshOnStart) {
- AutoUpdateManager.runImmediate(this);
- }
-
+ if (intent.hasExtra(EXTRA_FEED_ID)) {
long feedId = intent.getLongExtra(EXTRA_FEED_ID, 0);
- if (tag != null) {
- loadFragment(tag, args);
- } else if (feedId > 0) {
+ Bundle args = intent.getBundleExtra(MainActivityStarter.EXTRA_FRAGMENT_ARGS);
+ if (feedId > 0) {
boolean startedFromSearch = intent.getBooleanExtra(EXTRA_STARTED_FROM_SEARCH, false);
boolean addToBackStack = intent.getBooleanExtra(EXTRA_ADD_TO_BACK_STACK, false);
if (startedFromSearch || addToBackStack) {
@@ -534,12 +527,26 @@ public class MainActivity extends CastEnabledActivity {
}
}
sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
+ } else if (intent.hasExtra(MainActivityStarter.EXTRA_FRAGMENT_TAG)) {
+ String tag = intent.getStringExtra(MainActivityStarter.EXTRA_FRAGMENT_TAG);
+ Bundle args = intent.getBundleExtra(MainActivityStarter.EXTRA_FRAGMENT_ARGS);
+ if (tag != null) {
+ loadFragment(tag, args);
+ }
+ sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else if (intent.getBooleanExtra(MainActivityStarter.EXTRA_OPEN_PLAYER, false)) {
sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
bottomSheetCallback.onSlide(null, 1.0f);
} else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
handleDeeplink(intent.getData());
}
+
+ if (intent.getBooleanExtra(MainActivityStarter.EXTRA_OPEN_DRAWER, false) && drawerLayout != null) {
+ drawerLayout.open();
+ }
+ if (intent.getBooleanExtra(EXTRA_REFRESH_ON_START, false)) {
+ AutoUpdateManager.runImmediate(this);
+ }
// to avoid handling the intent twice when the configuration changes
setIntent(new Intent(MainActivity.this, MainActivity.class));
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/CoverLoader.java b/app/src/main/java/de/danoeh/antennapod/adapter/CoverLoader.java
index dc82e3adc..1d06bf07c 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/CoverLoader.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/CoverLoader.java
@@ -1,40 +1,28 @@
package de.danoeh.antennapod.adapter;
-import android.content.Context;
import android.graphics.drawable.Drawable;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.content.ContextCompat;
-import androidx.core.graphics.ColorUtils;
-import androidx.palette.graphics.Palette;
-
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
-
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.CustomViewTarget;
-
-import java.lang.ref.WeakReference;
-
import com.bumptech.glide.request.transition.Transition;
-
-import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.storage.preferences.UserPreferences;
-import de.danoeh.antennapod.ui.common.ThemeUtils;
-import de.danoeh.antennapod.ui.glide.PaletteBitmap;
+
+import java.lang.ref.WeakReference;
public class CoverLoader {
private int resource = 0;
private String uri;
private String fallbackUri;
- private TextView txtvPlaceholder;
private ImageView imgvCover;
private boolean textAndImageCombined;
private MainActivity activity;
+ private TextView fallbackTitle;
public CoverLoader(MainActivity activity) {
this.activity = activity;
@@ -60,31 +48,30 @@ public class CoverLoader {
return this;
}
- public CoverLoader withPlaceholderView(TextView placeholderView) {
- txtvPlaceholder = placeholderView;
+ public CoverLoader withPlaceholderView(TextView title) {
+ this.fallbackTitle = title;
return this;
}
/**
* Set cover text and if it should be shown even if there is a cover image.
- *
- * @param placeholderView Cover text.
+ * @param fallbackTitle Fallback title text
* @param textAndImageCombined Show cover text even if there is a cover image?
*/
@NonNull
- public CoverLoader withPlaceholderView(@NonNull TextView placeholderView, boolean textAndImageCombined) {
- this.txtvPlaceholder = placeholderView;
+ public CoverLoader withPlaceholderView(TextView fallbackTitle, boolean textAndImageCombined) {
+ this.fallbackTitle = fallbackTitle;
this.textAndImageCombined = textAndImageCombined;
return this;
}
public void load() {
- CoverTarget coverTarget = new CoverTarget(txtvPlaceholder, imgvCover, textAndImageCombined);
+ CoverTarget coverTarget = new CoverTarget(fallbackTitle, imgvCover, textAndImageCombined);
if (resource != 0) {
Glide.with(activity).clear(coverTarget);
imgvCover.setImageResource(resource);
- CoverTarget.setPlaceholderVisibility(txtvPlaceholder, textAndImageCombined, null);
+ CoverTarget.setTitleVisibility(fallbackTitle, textAndImageCombined);
return;
}
@@ -92,14 +79,14 @@ public class CoverLoader {
.fitCenter()
.dontAnimate();
- RequestBuilder<PaletteBitmap> builder = Glide.with(activity)
- .as(PaletteBitmap.class)
+ RequestBuilder<Drawable> builder = Glide.with(activity)
+ .as(Drawable.class)
.load(uri)
.apply(options);
- if (fallbackUri != null && txtvPlaceholder != null && imgvCover != null) {
+ if (fallbackUri != null) {
builder = builder.error(Glide.with(activity)
- .as(PaletteBitmap.class)
+ .as(Drawable.class)
.load(fallbackUri)
.apply(options));
}
@@ -107,64 +94,41 @@ public class CoverLoader {
builder.into(coverTarget);
}
- static class CoverTarget extends CustomViewTarget<ImageView, PaletteBitmap> {
- private final WeakReference<TextView> placeholder;
+ static class CoverTarget extends CustomViewTarget<ImageView, Drawable> {
+ private final WeakReference<TextView> fallbackTitle;
private final WeakReference<ImageView> cover;
- private boolean textAndImageCombined;
+ private final boolean textAndImageCombined;
- public CoverTarget(TextView txtvPlaceholder, ImageView imgvCover, boolean textAndImageCombined) {
- super(imgvCover);
- if (txtvPlaceholder != null) {
- txtvPlaceholder.setVisibility(View.VISIBLE);
- }
- placeholder = new WeakReference<>(txtvPlaceholder);
- cover = new WeakReference<>(imgvCover);
+ public CoverTarget(TextView fallbackTitle, ImageView coverImage, boolean textAndImageCombined) {
+ super(coverImage);
+ this.fallbackTitle = new WeakReference<>(fallbackTitle);
+ this.cover = new WeakReference<>(coverImage);
this.textAndImageCombined = textAndImageCombined;
}
@Override
public void onLoadFailed(Drawable errorDrawable) {
- setPlaceholderVisibility(this.placeholder.get(), true, null);
+ setTitleVisibility(fallbackTitle.get(), true);
}
@Override
- public void onResourceReady(@NonNull PaletteBitmap resource,
- @Nullable Transition<? super PaletteBitmap> transition) {
+ public void onResourceReady(@NonNull Drawable resource,
+ @Nullable Transition<? super Drawable> transition) {
ImageView ivCover = cover.get();
- ivCover.setImageBitmap(resource.bitmap);
- setPlaceholderVisibility(placeholder.get(), textAndImageCombined, resource.palette);
+ ivCover.setImageDrawable(resource);
+ setTitleVisibility(fallbackTitle.get(), textAndImageCombined);
}
@Override
protected void onResourceCleared(@Nullable Drawable placeholder) {
ImageView ivCover = cover.get();
ivCover.setImageDrawable(placeholder);
- setPlaceholderVisibility(this.placeholder.get(), textAndImageCombined, null);
+ setTitleVisibility(fallbackTitle.get(), textAndImageCombined);
}
- static void setPlaceholderVisibility(TextView placeholder, boolean textAndImageCombined, Palette palette) {
- boolean showTitle = UserPreferences.shouldShowSubscriptionTitle();
- if (placeholder != null) {
- if (textAndImageCombined || showTitle) {
- final Context context = placeholder.getContext();
- placeholder.setVisibility(View.VISIBLE);
- int bgColor = ContextCompat.getColor(context, R.color.feed_text_bg);
- if (palette == null || !showTitle) {
- placeholder.setBackgroundColor(bgColor);
- placeholder.setTextColor(ThemeUtils.getColorFromAttr(placeholder.getContext(),
- android.R.attr.textColorPrimary));
- return;
- }
- int dominantColor = palette.getDominantColor(bgColor);
- int textColor = ContextCompat.getColor(context, R.color.white);
- if (ColorUtils.calculateLuminance(dominantColor) > 0.5) {
- textColor = ContextCompat.getColor(context, R.color.black);
- }
- placeholder.setTextColor(textColor);
- placeholder.setBackgroundColor(dominantColor);
- } else {
- placeholder.setVisibility(View.INVISIBLE);
- }
+ static void setTitleVisibility(TextView fallbackTitle, boolean textAndImageCombined) {
+ if (fallbackTitle != null) {
+ fallbackTitle.setVisibility(textAndImageCombined ? View.VISIBLE : View.GONE);
}
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/HorizontalFeedListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/HorizontalFeedListAdapter.java
index 9d2713f48..9a578da6a 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/HorizontalFeedListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/HorizontalFeedListAdapter.java
@@ -16,10 +16,17 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
-public class HorizontalFeedListAdapter extends RecyclerView.Adapter<HorizontalFeedListAdapter.Holder> {
+import android.view.ContextMenu;
+import android.view.MenuInflater;
+import androidx.annotation.Nullable;
+
+public class HorizontalFeedListAdapter extends RecyclerView.Adapter<HorizontalFeedListAdapter.Holder>
+ implements View.OnCreateContextMenuListener {
private final WeakReference<MainActivity> mainActivityRef;
private final List<Feed> data = new ArrayList<>();
private int dummyViews = 0;
+ private Feed longPressedItem;
+
public HorizontalFeedListAdapter(MainActivity mainActivity) {
this.mainActivityRef = new WeakReference<>(mainActivity);
@@ -57,6 +64,13 @@ public class HorizontalFeedListAdapter extends RecyclerView.Adapter<HorizontalFe
holder.imageView.setOnClickListener(v ->
mainActivityRef.get().loadChildFragment(FeedItemlistFragment.newInstance(podcast.getId())));
+ holder.imageView.setOnCreateContextMenuListener(this);
+ holder.imageView.setOnLongClickListener(v -> {
+ int currentItemPosition = holder.getBindingAdapterPosition();
+ longPressedItem = data.get(currentItemPosition);
+ return false;
+ });
+
Glide.with(mainActivityRef.get())
.load(podcast.getImageUrl())
.apply(new RequestOptions()
@@ -66,6 +80,11 @@ public class HorizontalFeedListAdapter extends RecyclerView.Adapter<HorizontalFe
.into(holder.imageView);
}
+ @Nullable
+ public Feed getLongPressedItem() {
+ return longPressedItem;
+ }
+
@Override
public long getItemId(int position) {
if (position >= data.size()) {
@@ -79,6 +98,16 @@ public class HorizontalFeedListAdapter extends RecyclerView.Adapter<HorizontalFe
return dummyViews + data.size();
}
+ @Override
+ public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
+ MenuInflater inflater = mainActivityRef.get().getMenuInflater();
+ if (longPressedItem == null) {
+ return;
+ }
+ inflater.inflate(R.menu.nav_feed_context, contextMenu);
+ contextMenu.setHeaderTitle(longPressedItem.getTitle());
+ }
+
static class Holder extends RecyclerView.ViewHolder {
SquareImageView imageView;
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsRecyclerAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsRecyclerAdapter.java
index 7be417984..bfa37b600 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsRecyclerAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsRecyclerAdapter.java
@@ -5,7 +5,6 @@ import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
-import android.text.TextUtils;
import android.view.ContextMenu;
import android.view.InputDevice;
import android.view.LayoutInflater;
@@ -17,20 +16,19 @@ import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.ImageView;
-import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
-import androidx.core.content.ContextCompat;
+import androidx.cardview.widget.CardView;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
+import com.google.android.material.elevation.SurfaceColors;
import java.lang.ref.WeakReference;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
@@ -39,7 +37,6 @@ import de.danoeh.antennapod.core.storage.NavDrawerData;
import de.danoeh.antennapod.fragment.FeedItemlistFragment;
import de.danoeh.antennapod.fragment.SubscriptionFragment;
import de.danoeh.antennapod.model.feed.Feed;
-import de.danoeh.antennapod.ui.common.TriangleLabelView;
/**
* Adapter for subscriptions
@@ -52,6 +49,7 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
private List<NavDrawerData.DrawerItem> listItems;
private NavDrawerData.DrawerItem selectedItem = null;
int longPressedPosition = 0; // used to init actionMode
+ private int columnCount = 3;
public SubscriptionsRecyclerAdapter(MainActivity mainActivity) {
super(mainActivity);
@@ -60,6 +58,10 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
setHasStableIds(true);
}
+ public void setColumnCount(int columnCount) {
+ this.columnCount = columnCount;
+ }
+
public Object getItem(int position) {
return listItems.get(position);
}
@@ -72,24 +74,7 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
@Override
public SubscriptionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mainActivityRef.get()).inflate(R.layout.subscription_item, parent, false);
- TextView feedTitle = itemView.findViewById(R.id.txtvTitle);
- RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) feedTitle.getLayoutParams();
- int topAndBottomItemId = R.id.imgvCover;
- int belowItemId = 0;
-
- if (viewType == COVER_WITH_TITLE) {
- topAndBottomItemId = 0;
- belowItemId = R.id.imgvCover;
- feedTitle.setBackgroundColor(
- ContextCompat.getColor(feedTitle.getContext(), R.color.feed_text_bg));
- int padding = (int) convertDpToPixel(feedTitle.getContext(), 6);
- feedTitle.setPadding(padding, padding, padding, padding);
- }
- params.addRule(RelativeLayout.BELOW, belowItemId);
- params.addRule(RelativeLayout.ALIGN_TOP, topAndBottomItemId);
- params.addRule(RelativeLayout.ALIGN_BOTTOM, topAndBottomItemId);
- feedTitle.setLayoutParams(params);
- feedTitle.setSingleLine(viewType == COVER_WITH_TITLE);
+ itemView.findViewById(R.id.titleLabel).setVisibility(viewType == COVER_WITH_TITLE ? View.VISIBLE : View.GONE);
return new SubscriptionViewHolder(itemView);
}
@@ -107,11 +92,11 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
holder.selectCheckbox.setChecked((isSelected(position)));
holder.selectCheckbox.setOnCheckedChangeListener((buttonView, isChecked)
-> setSelected(holder.getBindingAdapterPosition(), isChecked));
- holder.imageView.setAlpha(0.6f);
+ holder.coverImage.setAlpha(0.6f);
holder.count.setVisibility(View.GONE);
} else {
holder.selectView.setVisibility(View.GONE);
- holder.imageView.setAlpha(1.0f);
+ holder.coverImage.setAlpha(1.0f);
}
holder.itemView.setOnLongClickListener(v -> {
@@ -224,55 +209,74 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
}
public class SubscriptionViewHolder extends RecyclerView.ViewHolder {
- private final TextView feedTitle;
- private final ImageView imageView;
- private final TriangleLabelView count;
+ private final TextView title;
+ private final ImageView coverImage;
+ private final TextView count;
+ private final TextView fallbackTitle;
private final FrameLayout selectView;
private final CheckBox selectCheckbox;
+ private final CardView card;
public SubscriptionViewHolder(@NonNull View itemView) {
super(itemView);
- feedTitle = itemView.findViewById(R.id.txtvTitle);
- imageView = itemView.findViewById(R.id.imgvCover);
- count = itemView.findViewById(R.id.triangleCountView);
- selectView = itemView.findViewById(R.id.selectView);
+ title = itemView.findViewById(R.id.titleLabel);
+ coverImage = itemView.findViewById(R.id.coverImage);
+ count = itemView.findViewById(R.id.countViewPill);
+ fallbackTitle = itemView.findViewById(R.id.fallbackTitleLabel);
+ selectView = itemView.findViewById(R.id.selectContainer);
selectCheckbox = itemView.findViewById(R.id.selectCheckBox);
+ card = itemView.findViewById(R.id.outerContainer);
}
public void bind(NavDrawerData.DrawerItem drawerItem) {
Drawable drawable = AppCompatResources.getDrawable(selectView.getContext(),
R.drawable.ic_checkbox_background);
selectView.setBackground(drawable); // Setting this in XML crashes API <= 21
- feedTitle.setText(drawerItem.getTitle());
- imageView.setContentDescription(drawerItem.getTitle());
- feedTitle.setVisibility(View.VISIBLE);
- if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL) {
- count.setCorner(TriangleLabelView.Corner.TOP_LEFT);
- }
-
+ title.setText(drawerItem.getTitle());
+ fallbackTitle.setText(drawerItem.getTitle());
+ coverImage.setContentDescription(drawerItem.getTitle());
if (drawerItem.getCounter() > 0) {
- count.setPrimaryText(NumberFormat.getInstance().format(drawerItem.getCounter()));
+ count.setText(NumberFormat.getInstance().format(drawerItem.getCounter()));
count.setVisibility(View.VISIBLE);
} else {
count.setVisibility(View.GONE);
}
+ CoverLoader coverLoader = new CoverLoader(mainActivityRef.get());
+ boolean textAndImageCombined;
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
- boolean textAndImageCombind = feed.isLocalFeed()
- && feed.getImageUrl() != null && feed.getImageUrl().startsWith(Feed.PREFIX_GENERATIVE_COVER);
- new CoverLoader(mainActivityRef.get())
- .withUri(feed.getImageUrl())
- .withPlaceholderView(feedTitle, textAndImageCombind)
- .withCoverView(imageView)
- .load();
+ textAndImageCombined = feed.isLocalFeed() && feed.getImageUrl() != null
+ && feed.getImageUrl().startsWith(Feed.PREFIX_GENERATIVE_COVER);
+ coverLoader.withUri(feed.getImageUrl());
} else {
- new CoverLoader(mainActivityRef.get())
- .withResource(R.drawable.ic_tag)
- .withPlaceholderView(feedTitle, true)
- .withCoverView(imageView)
- .load();
+ textAndImageCombined = true;
+ coverLoader.withResource(R.drawable.ic_tag);
+ }
+ if (UserPreferences.shouldShowSubscriptionTitle()) {
+ // No need for fallback title when already showing title
+ fallbackTitle.setVisibility(View.GONE);
+ } else {
+ coverLoader.withPlaceholderView(fallbackTitle, textAndImageCombined);
+ }
+ coverLoader.withCoverView(coverImage);
+ coverLoader.load();
+
+ float density = mainActivityRef.get().getResources().getDisplayMetrics().density;
+ card.setCardBackgroundColor(SurfaceColors.getColorForElevation(mainActivityRef.get(), 1 * density));
+
+ int textPadding = columnCount <= 3 ? 16 : 8;
+ title.setPadding(textPadding, textPadding, textPadding, textPadding);
+ fallbackTitle.setPadding(textPadding, textPadding, textPadding, textPadding);
+
+ int textSize = 14;
+ if (columnCount == 3) {
+ textSize = 15;
+ } else if (columnCount == 2) {
+ textSize = 16;
}
+ title.setTextSize(textSize);
+ fallbackTitle.setTextSize(textSize);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java
deleted file mode 100644
index 69f112c3b..000000000
--- a/app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package de.danoeh.antennapod.config;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Build;
-
-import android.os.Bundle;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.DownloadAuthenticationActivity;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.core.DownloadServiceCallbacks;
-import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest;
-import de.danoeh.antennapod.fragment.CompletedDownloadsFragment;
-import de.danoeh.antennapod.fragment.QueueFragment;
-
-
-public class DownloadServiceCallbacksImpl implements DownloadServiceCallbacks {
-
- @Override
- public PendingIntent getNotificationContentIntent(Context context) {
- Intent intent = new Intent(context, MainActivity.class);
- intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, CompletedDownloadsFragment.TAG);
- return PendingIntent.getActivity(context,
- R.id.pending_intent_download_service_notification, intent,
- PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
- }
-
- @Override
- public PendingIntent getAuthentificationNotificationContentIntent(Context context, DownloadRequest request) {
- final Intent activityIntent = new Intent(context.getApplicationContext(), DownloadAuthenticationActivity.class);
- activityIntent.setAction("request" + request.getFeedfileId());
- activityIntent.putExtra(DownloadAuthenticationActivity.ARG_DOWNLOAD_REQUEST, request);
- return PendingIntent.getActivity(context.getApplicationContext(),
- request.getSource().hashCode(), activityIntent,
- PendingIntent.FLAG_ONE_SHOT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
- }
-
- @Override
- public PendingIntent getReportNotificationContentIntent(Context context) {
- Intent intent = new Intent(context, MainActivity.class);
- intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, CompletedDownloadsFragment.TAG);
- Bundle args = new Bundle();
- args.putBoolean(CompletedDownloadsFragment.ARG_SHOW_LOGS, true);
- intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args);
- return PendingIntent.getActivity(context, R.id.pending_intent_download_service_report, intent,
- PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
- }
-
- @Override
- public PendingIntent getAutoDownloadReportNotificationContentIntent(Context context) {
- Intent intent = new Intent(context, MainActivity.class);
- intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, QueueFragment.TAG);
- return PendingIntent.getActivity(context, R.id.pending_intent_download_service_autodownload_report, intent,
- PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
- }
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
index b39b41897..6d91765da 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
@@ -4,6 +4,8 @@ import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
@@ -33,6 +35,8 @@ import de.danoeh.antennapod.fragment.swipeactions.SwipeActions;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
+import de.danoeh.antennapod.model.feed.SortOrder;
+import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.view.EmptyViewHandler;
import de.danoeh.antennapod.view.EpisodeItemListRecyclerView;
import de.danoeh.antennapod.view.LiftOnScrollListener;
@@ -77,6 +81,8 @@ public class CompletedDownloadsFragment extends Fragment
MaterialToolbar toolbar = root.findViewById(R.id.toolbar);
toolbar.setTitle(R.string.downloads_label);
toolbar.inflateMenu(R.menu.downloads_completed);
+ inflateSortMenu(toolbar);
+
toolbar.setOnMenuItemClickListener(this);
toolbar.setOnLongClickListener(v -> {
recyclerView.scrollToPosition(5);
@@ -139,6 +145,19 @@ public class CompletedDownloadsFragment extends Fragment
return root;
}
+ private void inflateSortMenu(MaterialToolbar toolbar) {
+ Menu menu = toolbar.getMenu();
+ MenuItem downloadsItem = menu.findItem(R.id.downloads_sort);
+ MenuInflater menuInflater = getActivity().getMenuInflater();
+ menuInflater.inflate(R.menu.sort_menu, downloadsItem.getSubMenu());
+
+ // Remove the sorting options that are not needed in this fragment
+ menu.findItem(R.id.sort_feed_title).setVisible(false);
+ menu.findItem(R.id.sort_random).setVisible(false);
+ menu.findItem(R.id.sort_smart_shuffle).setVisible(false);
+ menu.findItem(R.id.keep_sorted).setVisible(false);
+ }
+
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putBoolean(KEY_UP_ARROW, displayUpArrow);
@@ -177,10 +196,21 @@ public class CompletedDownloadsFragment extends Fragment
} else if (item.getItemId() == R.id.action_search) {
((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance());
return true;
+ } else {
+ SortOrder sortOrder = MenuItemToSortOrderConverter.convert(item);
+ if (sortOrder != null) {
+ setSortOrder(sortOrder);
+ return true;
+ }
}
return false;
}
+ private void setSortOrder(SortOrder sortOrder) {
+ UserPreferences.setDownloadsSortedOrder(sortOrder);
+ loadItems();
+ }
+
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEventMainThread(DownloadEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
@@ -279,7 +309,9 @@ public class CompletedDownloadsFragment extends Fragment
}
emptyView.hide();
disposable = Observable.fromCallable(() -> {
- List<FeedItem> downloadedItems = DBReader.getDownloadedItems();
+ SortOrder sortOrder = UserPreferences.getDownloadsSortedOrder();
+ List<FeedItem> downloadedItems = DBReader.getDownloadedItems(sortOrder);
+
List<Long> mediaIds = new ArrayList<>();
if (runningDownloads == null) {
return downloadedItems;
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DiscoveryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DiscoveryFragment.java
index 88b9ac8f1..16ccb2af4 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/DiscoveryFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/DiscoveryFragment.java
@@ -14,17 +14,25 @@ import android.widget.Button;
import android.widget.GridView;
import android.widget.ProgressBar;
import android.widget.TextView;
-
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
-
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.MaterialAutoCompleteTextView;
import com.google.android.material.textfield.TextInputLayout;
-
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
+import de.danoeh.antennapod.adapter.itunes.ItunesAdapter;
import de.danoeh.antennapod.core.BuildConfig;
+import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.event.DiscoveryDefaultUpdateEvent;
+import de.danoeh.antennapod.net.discovery.ItunesTopListLoader;
+import de.danoeh.antennapod.net.discovery.PodcastSearchResult;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
import org.greenrobot.eventbus.EventBus;
import java.util.ArrayList;
@@ -35,20 +43,13 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
-import de.danoeh.antennapod.adapter.itunes.ItunesAdapter;
-import de.danoeh.antennapod.event.DiscoveryDefaultUpdateEvent;
-import de.danoeh.antennapod.net.discovery.ItunesTopListLoader;
-import de.danoeh.antennapod.net.discovery.PodcastSearchResult;
-import io.reactivex.disposables.Disposable;
-
/**
* Searches iTunes store for top podcasts and displays results in a list.
*/
public class DiscoveryFragment extends Fragment implements Toolbar.OnMenuItemClickListener {
private static final String TAG = "ItunesSearchFragment";
+ private static final int NUM_OF_TOP_PODCASTS = 25;
private SharedPreferences prefs;
/**
@@ -188,19 +189,23 @@ public class DiscoveryFragment extends Fragment implements Toolbar.OnMenuItemCli
}
ItunesTopListLoader loader = new ItunesTopListLoader(getContext());
- disposable = loader.loadToplist(country, 25).subscribe(
- podcasts -> {
- progressBar.setVisibility(View.GONE);
- topList = podcasts;
- updateData(topList);
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- progressBar.setVisibility(View.GONE);
- txtvError.setText(error.getMessage());
- txtvError.setVisibility(View.VISIBLE);
- butRetry.setOnClickListener(v -> loadToplist(country));
- butRetry.setVisibility(View.VISIBLE);
- });
+ disposable = Observable.fromCallable(() ->
+ loader.loadToplist(country, NUM_OF_TOP_PODCASTS, DBReader.getFeedList()))
+ .subscribeOn(Schedulers.io())
+ .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.getMessage());
+ txtvError.setVisibility(View.VISIBLE);
+ butRetry.setOnClickListener(v -> loadToplist(country));
+ butRetry.setVisibility(View.VISIBLE);
+ });
}
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/MenuItemToSortOrderConverter.java b/app/src/main/java/de/danoeh/antennapod/fragment/MenuItemToSortOrderConverter.java
new file mode 100644
index 000000000..51911b122
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/MenuItemToSortOrderConverter.java
@@ -0,0 +1,40 @@
+package de.danoeh.antennapod.fragment;
+
+import android.view.MenuItem;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.model.feed.SortOrder;
+
+public class MenuItemToSortOrderConverter {
+
+ public static SortOrder convert(MenuItem item) {
+ final int itemId = item.getItemId();
+
+ if (itemId == R.id.sort_episode_title_asc) {
+ return SortOrder.EPISODE_TITLE_A_Z;
+ } else if (itemId == R.id.sort_episode_title_desc) {
+ return SortOrder.EPISODE_TITLE_Z_A;
+ } else if (itemId == R.id.sort_date_asc) {
+ return SortOrder.DATE_OLD_NEW;
+ } else if (itemId == R.id.sort_date_desc) {
+ return SortOrder.DATE_NEW_OLD;
+ } else if (itemId == R.id.sort_duration_asc) {
+ return SortOrder.DURATION_SHORT_LONG;
+ } else if (itemId == R.id.sort_duration_desc) {
+ return SortOrder.DURATION_LONG_SHORT;
+ } else if (itemId == R.id.sort_feed_title_asc) {
+ return SortOrder.FEED_TITLE_A_Z;
+ } else if (itemId == R.id.sort_feed_title_desc) {
+ return SortOrder.FEED_TITLE_Z_A;
+ } else if (itemId == R.id.sort_random) {
+ return SortOrder.RANDOM;
+ } else if (itemId == R.id.sort_smart_shuffle_asc) {
+ return SortOrder.SMART_SHUFFLE_OLD_NEW;
+ } else if (itemId == R.id.sort_smart_shuffle_desc) {
+ return SortOrder.SMART_SHUFFLE_NEW_OLD;
+ }
+
+ return null;
+ }
+
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java
index 7c3ed4f2f..e155e467d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java
@@ -40,6 +40,7 @@ import de.danoeh.antennapod.event.FeedListUpdateEvent;
import de.danoeh.antennapod.event.QueueEvent;
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.ui.appstartintent.MainActivityStarter;
import de.danoeh.antennapod.ui.home.HomeFragment;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -338,7 +339,15 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
@Override
public boolean onItemLongClick(int position) {
if (position < navAdapter.getFragmentTags().size()) {
- DrawerPreferencesDialog.show(getContext(), () -> navAdapter.notifyDataSetChanged());
+ DrawerPreferencesDialog.show(getContext(), () -> {
+ navAdapter.notifyDataSetChanged();
+ if (UserPreferences.getHiddenDrawerItems().contains(getLastNavFragment(getContext()))) {
+ new MainActivityStarter(getContext())
+ .withFragmentLoaded(UserPreferences.getDefaultPage())
+ .withDrawerOpen()
+ .start();
+ }
+ });
return true;
} else {
contextPressedItem = flatItemList.get(position - navAdapter.getSubscriptionOffset());
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 12fa20d05..4e8999d0f 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -10,6 +10,7 @@ import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.LayoutInflater;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
@@ -256,8 +257,8 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
boolean keepSorted = UserPreferences.isQueueKeepSorted();
toolbar.getMenu().findItem(R.id.queue_lock).setChecked(UserPreferences.isQueueLocked());
toolbar.getMenu().findItem(R.id.queue_lock).setVisible(!keepSorted);
- toolbar.getMenu().findItem(R.id.queue_sort_random).setVisible(!keepSorted);
- toolbar.getMenu().findItem(R.id.queue_keep_sorted).setChecked(keepSorted);
+ toolbar.getMenu().findItem(R.id.sort_random).setVisible(!keepSorted);
+ toolbar.getMenu().findItem(R.id.keep_sorted).setChecked(keepSorted);
MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(),
R.id.refresh_item, DownloadService.isRunning && DownloadService.isDownloadingFeeds());
}
@@ -286,40 +287,7 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
};
conDialog.createNewDialog().show();
return true;
- } else if (itemId == R.id.queue_sort_episode_title_asc) {
- setSortOrder(SortOrder.EPISODE_TITLE_A_Z);
- return true;
- } else if (itemId == R.id.queue_sort_episode_title_desc) {
- setSortOrder(SortOrder.EPISODE_TITLE_Z_A);
- return true;
- } else if (itemId == R.id.queue_sort_date_asc) {
- setSortOrder(SortOrder.DATE_OLD_NEW);
- return true;
- } else if (itemId == R.id.queue_sort_date_desc) {
- setSortOrder(SortOrder.DATE_NEW_OLD);
- return true;
- } else if (itemId == R.id.queue_sort_duration_asc) {
- setSortOrder(SortOrder.DURATION_SHORT_LONG);
- return true;
- } else if (itemId == R.id.queue_sort_duration_desc) {
- setSortOrder(SortOrder.DURATION_LONG_SHORT);
- return true;
- } else if (itemId == R.id.queue_sort_feed_title_asc) {
- setSortOrder(SortOrder.FEED_TITLE_A_Z);
- return true;
- } else if (itemId == R.id.queue_sort_feed_title_desc) {
- setSortOrder(SortOrder.FEED_TITLE_Z_A);
- return true;
- } else if (itemId == R.id.queue_sort_random) {
- setSortOrder(SortOrder.RANDOM);
- return true;
- } else if (itemId == R.id.queue_sort_smart_shuffle_asc) {
- setSortOrder(SortOrder.SMART_SHUFFLE_OLD_NEW);
- return true;
- } else if (itemId == R.id.queue_sort_smart_shuffle_desc) {
- setSortOrder(SortOrder.SMART_SHUFFLE_NEW_OLD);
- return true;
- } else if (itemId == R.id.queue_keep_sorted) {
+ } else if (itemId == R.id.keep_sorted) {
boolean keepSortedOld = UserPreferences.isQueueKeepSorted();
boolean keepSortedNew = !keepSortedOld;
UserPreferences.setQueueKeepSorted(keepSortedNew);
@@ -335,6 +303,12 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
} else if (itemId == R.id.action_search) {
((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance());
return true;
+ } else {
+ SortOrder sortOrder = MenuItemToSortOrderConverter.convert(item);
+ if (sortOrder != null) {
+ setSortOrder(sortOrder);
+ return true;
+ }
}
return false;
}
@@ -444,6 +418,10 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
}
((MainActivity) getActivity()).setupToolbarToggle(toolbar, displayUpArrow);
toolbar.inflateMenu(R.menu.queue);
+
+ MenuItem queueItem = toolbar.getMenu().findItem(R.id.queue_sort);
+ MenuInflater menuInflater = getActivity().getMenuInflater();
+ menuInflater.inflate(R.menu.sort_menu, queueItem.getSubMenu());
refreshToolbarState();
progressBar = root.findViewById(R.id.progressBar);
progressBar.setVisibility(View.VISIBLE);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QuickFeedDiscoveryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QuickFeedDiscoveryFragment.java
index acdd1e1c7..d5192061c 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QuickFeedDiscoveryFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QuickFeedDiscoveryFragment.java
@@ -5,7 +5,6 @@ import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.DisplayMetrics;
-import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
@@ -16,20 +15,23 @@ import android.widget.Button;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.TextView;
-
+import androidx.fragment.app.Fragment;
import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.net.discovery.ItunesTopListLoader;
-import de.danoeh.antennapod.net.discovery.PodcastSearchResult;
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
import de.danoeh.antennapod.adapter.FeedDiscoverAdapter;
+import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.event.DiscoveryDefaultUpdateEvent;
+import de.danoeh.antennapod.net.discovery.ItunesTopListLoader;
+import de.danoeh.antennapod.net.discovery.PodcastSearchResult;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.List;
@@ -138,26 +140,29 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView.
return;
}
- disposable = loader.loadToplist(countryCode, NUM_SUGGESTIONS)
+ disposable = Observable.fromCallable(() ->
+ loader.loadToplist(countryCode, NUM_SUGGESTIONS, DBReader.getFeedList()))
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
.subscribe(
- podcasts -> {
- errorView.setVisibility(View.GONE);
- if (podcasts.size() == 0) {
- errorTextView.setText(getResources().getText(R.string.search_status_no_results));
- errorView.setVisibility(View.VISIBLE);
- discoverGridLayout.setVisibility(View.INVISIBLE);
- } else {
- discoverGridLayout.setVisibility(View.VISIBLE);
- adapter.updateData(podcasts);
- }
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- errorTextView.setText(error.getLocalizedMessage());
+ podcasts -> {
+ errorView.setVisibility(View.GONE);
+ if (podcasts.size() == 0) {
+ errorTextView.setText(getResources().getText(R.string.search_status_no_results));
errorView.setVisibility(View.VISIBLE);
discoverGridLayout.setVisibility(View.INVISIBLE);
- errorRetry.setVisibility(View.VISIBLE);
- errorRetry.setOnClickListener((listener) -> loadToplist());
- });
+ } else {
+ discoverGridLayout.setVisibility(View.VISIBLE);
+ adapter.updateData(podcasts);
+ }
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ errorTextView.setText(error.getLocalizedMessage());
+ errorView.setVisibility(View.VISIBLE);
+ discoverGridLayout.setVisibility(View.INVISIBLE);
+ errorRetry.setVisibility(View.VISIBLE);
+ errorRetry.setOnClickListener(v -> loadToplist());
+ });
}
@Override
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 77fec7a8f..d2aa35549 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
@@ -54,6 +54,9 @@ import org.greenrobot.eventbus.ThreadMode;
import java.util.Collections;
import java.util.List;
+import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
+import de.danoeh.antennapod.event.FeedListUpdateEvent;
+
/**
* Performs a search operation on all feeds or one specific feed and displays the search result.
@@ -132,6 +135,7 @@ public class SearchFragment extends Fragment {
recyclerView = layout.findViewById(R.id.recyclerView);
recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
+ registerForContextMenu(recyclerView);
adapter = new EpisodeItemListAdapter((MainActivity) getActivity()) {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
@@ -146,7 +150,14 @@ public class SearchFragment extends Fragment {
LinearLayoutManager layoutManagerFeeds = new LinearLayoutManager(getActivity());
layoutManagerFeeds.setOrientation(RecyclerView.HORIZONTAL);
recyclerViewFeeds.setLayoutManager(layoutManagerFeeds);
- adapterFeeds = new HorizontalFeedListAdapter((MainActivity) getActivity());
+ adapterFeeds = new HorizontalFeedListAdapter((MainActivity) getActivity()) {
+ @Override
+ public void onCreateContextMenu(ContextMenu contextMenu, View view,
+ ContextMenu.ContextMenuInfo contextMenuInfo) {
+ super.onCreateContextMenu(contextMenu, view, contextMenuInfo);
+ MenuItemUtils.setOnClickListeners(contextMenu, SearchFragment.this::onContextItemSelected);
+ }
+ };
recyclerViewFeeds.setAdapter(adapterFeeds);
emptyViewHandler = new EmptyViewHandler(getContext());
@@ -241,12 +252,21 @@ public class SearchFragment extends Fragment {
@Override
public boolean onContextItemSelected(@NonNull MenuItem item) {
+ Feed selectedFeedItem = adapterFeeds.getLongPressedItem();
+ if (selectedFeedItem != null
+ && FeedMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedFeedItem, () -> { })) {
+ return true;
+ }
FeedItem selectedItem = adapter.getLongPressedItem();
- if (selectedItem == null) {
- Log.i(TAG, "Selected item at current position was null, ignoring selection");
- return super.onContextItemSelected(item);
+ if (selectedItem != null && FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem)) {
+ return true;
}
- return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
+ return super.onContextItemSelected(item);
+ }
+
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onFeedListChanged(FeedListUpdateEvent event) {
+ search();
}
@Subscribe(threadMode = ThreadMode.MAIN)
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
index 2800537e2..cc13f4ce3 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
@@ -1,8 +1,6 @@
package de.danoeh.antennapod.fragment;
-import android.annotation.SuppressLint;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
@@ -17,7 +15,6 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.annotation.StringRes;
import com.google.android.material.appbar.MaterialToolbar;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
@@ -28,7 +25,6 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.joanzapata.iconify.Iconify;
import com.leinardi.android.speeddial.SpeedDialView;
-import de.danoeh.antennapod.dialog.TagSettingsDialog;
import de.danoeh.antennapod.ui.statistics.StatisticsFragment;
import de.danoeh.antennapod.view.LiftOnScrollListener;
import org.greenrobot.eventbus.EventBus;
@@ -36,15 +32,12 @@ import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Locale;
-import java.util.concurrent.Callable;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.SubscriptionsRecyclerAdapter;
-import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.event.FeedListUpdateEvent;
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
@@ -52,16 +45,15 @@ import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.storage.DBReader;
-import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.NavDrawerData;
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.dialog.FeedSortDialog;
-import de.danoeh.antennapod.dialog.RemoveFeedDialog;
import de.danoeh.antennapod.dialog.RenameItemDialog;
import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog;
import de.danoeh.antennapod.fragment.actions.FeedMultiSelectActionHandler;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.view.EmptyViewHandler;
+import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
@@ -150,7 +142,6 @@ public class SubscriptionFragment extends Fragment
}
subscriptionRecycler = root.findViewById(R.id.subscriptions_grid);
- setColumnNumber(prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()));
subscriptionRecycler.addItemDecoration(new SubscriptionsRecyclerAdapter.GridDividerItemDecorator());
registerForContextMenu(subscriptionRecycler);
subscriptionRecycler.addOnScrollListener(new LiftOnScrollListener(root.findViewById(R.id.appbar)));
@@ -161,6 +152,7 @@ public class SubscriptionFragment extends Fragment
MenuItemUtils.setOnClickListeners(menu, SubscriptionFragment.this::onContextItemSelected);
}
};
+ setColumnNumber(prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()));
subscriptionAdapter.setOnSelectModeListener(this);
subscriptionRecycler.setAdapter(subscriptionAdapter);
setupEmptyView();
@@ -259,6 +251,7 @@ public class SubscriptionFragment extends Fragment
private void setColumnNumber(int columns) {
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(),
columns, RecyclerView.VERTICAL, false);
+ subscriptionAdapter.setColumnCount(columns);
subscriptionRecycler.setLayoutManager(gridLayoutManager);
prefs.edit().putInt(PREF_NUM_COLUMNS, columns).apply();
refreshToolbarState();
@@ -350,43 +343,11 @@ public class SubscriptionFragment extends Fragment
}
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
- if (itemId == R.id.remove_all_inbox_item) {
- displayConfirmationDialog(
- R.string.remove_all_inbox_label,
- R.string.remove_all_inbox_confirmation_msg,
- () -> DBWriter.removeFeedNewFlag(feed.getId()));
- return true;
- } else if (itemId == R.id.edit_tags) {
- TagSettingsDialog.newInstance(Collections.singletonList(feed.getPreferences()))
- .show(getChildFragmentManager(), TagSettingsDialog.TAG);
- return true;
- } else if (itemId == R.id.rename_item) {
- new RenameItemDialog(getActivity(), feed).show();
- return true;
- } else if (itemId == R.id.remove_feed) {
- RemoveFeedDialog.show(getContext(), feed);
- return true;
- } else if (itemId == R.id.multi_select) {
+ if (itemId == R.id.multi_select) {
speedDialView.setVisibility(View.VISIBLE);
return subscriptionAdapter.onContextItemSelected(item);
}
- return super.onContextItemSelected(item);
- }
-
- private <T> void displayConfirmationDialog(@StringRes int title, @StringRes int message, Callable<? extends T> task) {
- ConfirmationDialog dialog = new ConfirmationDialog(getActivity(), title, message) {
- @Override
- @SuppressLint("CheckResult")
- public void onConfirmButtonPressed(DialogInterface clickedDialog) {
- clickedDialog.dismiss();
- Observable.fromCallable(task)
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(result -> loadSubscriptions(),
- error -> Log.e(TAG, Log.getStackTraceString(error)));
- }
- };
- dialog.createNewDialog().show();
+ return FeedMenuHandler.onMenuItemClicked(this, item.getItemId(), feed, this::loadSubscriptions);
}
@Subscribe(threadMode = ThreadMode.MAIN)
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java
index caf555964..66f592af2 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java
@@ -5,18 +5,19 @@ import android.os.Build;
import android.os.Bundle;
import android.widget.ListView;
import androidx.appcompat.app.AlertDialog;
-import com.google.android.material.snackbar.Snackbar;
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import androidx.core.app.ActivityCompat;
+import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import com.google.android.material.snackbar.Snackbar;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.PreferenceActivity;
-import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.dialog.DrawerPreferencesDialog;
import de.danoeh.antennapod.dialog.FeedSortDialog;
import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog;
import de.danoeh.antennapod.event.PlayerStatusEvent;
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
+import de.danoeh.antennapod.storage.preferences.UserPreferences;
import org.greenrobot.eventbus.EventBus;
import java.util.List;
@@ -37,22 +38,16 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat {
}
private void setupInterfaceScreen() {
- findPreference(UserPreferences.PREF_THEME)
- .setOnPreferenceChangeListener(
- (preference, newValue) -> {
- ActivityCompat.recreate(getActivity());
- return true;
- });
-
+ Preference.OnPreferenceChangeListener restartApp = (preference, newValue) -> {
+ ActivityCompat.recreate(getActivity());
+ return true;
+ };
+ findPreference(UserPreferences.PREF_THEME).setOnPreferenceChangeListener(restartApp);
+ findPreference(UserPreferences.PREF_THEME_BLACK).setOnPreferenceChangeListener(restartApp);
+ findPreference(UserPreferences.PREF_TINTED_COLORS).setOnPreferenceChangeListener(restartApp);
if (Build.VERSION.SDK_INT < 31) {
findPreference(UserPreferences.PREF_TINTED_COLORS).setVisible(false);
}
- findPreference(UserPreferences.PREF_TINTED_COLORS)
- .setOnPreferenceChangeListener(
- (preference, newValue) -> {
- ActivityCompat.recreate(getActivity());
- return true;
- });
findPreference(UserPreferences.PREF_SHOW_TIME_LEFT)
.setOnPreferenceChangeListener(
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 de6056063..7aee499da 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
@@ -14,6 +14,19 @@ import de.danoeh.antennapod.dialog.IntraFeedSortDialog;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.SortOrder;
import org.apache.commons.lang3.StringUtils;
+import android.content.DialogInterface;
+import android.annotation.SuppressLint;
+import androidx.fragment.app.Fragment;
+import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.dialog.RemoveFeedDialog;
+import de.danoeh.antennapod.dialog.RenameItemDialog;
+import de.danoeh.antennapod.dialog.TagSettingsDialog;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
+import java.util.Collections;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
/**
* Handles interactions with the FeedItemMenu.
@@ -75,4 +88,38 @@ public class FeedMenuHandler {
sortDialog.openDialog();
}
+ public static boolean onMenuItemClicked(@NonNull Fragment fragment, int menuItemId,
+ @NonNull Feed selectedFeed, Runnable callback) {
+ @NonNull Context context = fragment.requireContext();
+ if (menuItemId == R.id.rename_folder_item) {
+ new RenameItemDialog(fragment.getActivity(), selectedFeed).show();
+ } else if (menuItemId == R.id.remove_all_inbox_item) {
+ ConfirmationDialog dialog = new ConfirmationDialog(fragment.getActivity(),
+ R.string.remove_all_inbox_label, R.string.remove_all_inbox_confirmation_msg) {
+ @Override
+ @SuppressLint("CheckResult")
+ public void onConfirmButtonPressed(DialogInterface clickedDialog) {
+ clickedDialog.dismiss();
+ Observable.fromCallable((Callable<Future>) () -> DBWriter.removeFeedNewFlag(selectedFeed.getId()))
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> callback.run(),
+ error -> Log.e(TAG, Log.getStackTraceString(error)));
+ }
+ };
+ dialog.createNewDialog().show();
+
+ } else if (menuItemId == R.id.edit_tags) {
+ TagSettingsDialog.newInstance(Collections.singletonList(selectedFeed.getPreferences()))
+ .show(fragment.getChildFragmentManager(), TagSettingsDialog.TAG);
+ } else if (menuItemId == R.id.rename_item) {
+ new RenameItemDialog(fragment.getActivity(), selectedFeed).show();
+ } else if (menuItemId == R.id.remove_feed) {
+ RemoveFeedDialog.show(context, selectedFeed);
+ } else {
+ return false;
+ }
+ return true;
+ }
+
}
diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java
index e093c067d..79d06de59 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java
@@ -133,5 +133,13 @@ public class PreferenceUpgrader {
"" + UserPreferences.EPISODE_CACHE_SIZE_UNLIMITED).apply();
}
}
+ if (oldVersion < 3010000) {
+ if (prefs.getString(UserPreferences.PREF_THEME, "system").equals("2")) {
+ prefs.edit()
+ .putString(UserPreferences.PREF_THEME, "1")
+ .putBoolean(UserPreferences.PREF_THEME_BLACK, true)
+ .apply();
+ }
+ }
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/ThemePreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/ThemePreference.java
new file mode 100644
index 000000000..30cbeb523
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/ThemePreference.java
@@ -0,0 +1,53 @@
+package de.danoeh.antennapod.preferences;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import androidx.cardview.widget.CardView;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+import com.google.android.material.elevation.SurfaceColors;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.databinding.ThemePreferenceBinding;
+import de.danoeh.antennapod.storage.preferences.UserPreferences;
+
+public class ThemePreference extends Preference {
+ ThemePreferenceBinding viewBinding;
+
+ public ThemePreference(Context context) {
+ super(context);
+ setLayoutResource(R.layout.theme_preference);
+ }
+
+ public ThemePreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setLayoutResource(R.layout.theme_preference);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ viewBinding = ThemePreferenceBinding.bind(holder.itemView);
+ updateUi();
+ }
+
+ void updateThemeCard(CardView card, UserPreferences.ThemePreference theme) {
+ float density = getContext().getResources().getDisplayMetrics().density;
+ int surfaceColor = SurfaceColors.getColorForElevation(getContext(), 1 * density);
+ int surfaceColorActive = SurfaceColors.getColorForElevation(getContext(), 32 * density);
+ UserPreferences.ThemePreference activeTheme = UserPreferences.getTheme();
+ card.setCardBackgroundColor(theme == activeTheme ? surfaceColorActive : surfaceColor);
+ card.setOnClickListener(v -> {
+ UserPreferences.setTheme(theme);
+ if (getOnPreferenceChangeListener() != null) {
+ getOnPreferenceChangeListener().onPreferenceChange(this, UserPreferences.getTheme());
+ }
+ updateUi();
+ });
+ }
+
+ void updateUi() {
+ updateThemeCard(viewBinding.themeSystemCard, UserPreferences.ThemePreference.SYSTEM);
+ updateThemeCard(viewBinding.themeLightCard, UserPreferences.ThemePreference.LIGHT);
+ updateThemeCard(viewBinding.themeDarkCard, UserPreferences.ThemePreference.DARK);
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/home/sections/DownloadsSection.java b/app/src/main/java/de/danoeh/antennapod/ui/home/sections/DownloadsSection.java
index 78c336335..0053b0e82 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/home/sections/DownloadsSection.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/home/sections/DownloadsSection.java
@@ -23,6 +23,8 @@ import de.danoeh.antennapod.fragment.CompletedDownloadsFragment;
import de.danoeh.antennapod.fragment.swipeactions.SwipeActions;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
+import de.danoeh.antennapod.model.feed.SortOrder;
+import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.ui.home.HomeSection;
import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
import io.reactivex.Observable;
@@ -121,7 +123,8 @@ public class DownloadsSection extends HomeSection {
if (disposable != null) {
disposable.dispose();
}
- disposable = Observable.fromCallable(DBReader::getDownloadedItems)
+ SortOrder sortOrder = UserPreferences.getDownloadsSortedOrder();
+ disposable = Observable.fromCallable(() -> DBReader.getDownloadedItems(sortOrder))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(downloads -> {
diff --git a/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java b/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java
index cdf688502..fd3ec9299 100644
--- a/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java
+++ b/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java
@@ -226,6 +226,10 @@ public class EpisodeItemViewHolder extends RecyclerView.ViewHolder {
}
private void updateDuration(PlaybackPositionEvent event) {
+ if (getFeedItem().getMedia() != null) {
+ getFeedItem().getMedia().setPosition(event.getPosition());
+ getFeedItem().getMedia().setDuration(event.getDuration());
+ }
int currentPosition = event.getPosition();
int timeDuration = event.getDuration();
int remainingTime = Math.max(timeDuration - currentPosition, 0);
diff --git a/app/src/main/res/drawable-nodpi/theme_preview_dark.png b/app/src/main/res/drawable-nodpi/theme_preview_dark.png
new file mode 100644
index 000000000..b4e1e0376
--- /dev/null
+++ b/app/src/main/res/drawable-nodpi/theme_preview_dark.png
Binary files differ
diff --git a/app/src/main/res/drawable-nodpi/theme_preview_light.png b/app/src/main/res/drawable-nodpi/theme_preview_light.png
new file mode 100644
index 000000000..39ef47b4f
--- /dev/null
+++ b/app/src/main/res/drawable-nodpi/theme_preview_light.png
Binary files differ
diff --git a/app/src/main/res/drawable-nodpi/theme_preview_system.png b/app/src/main/res/drawable-nodpi/theme_preview_system.png
new file mode 100644
index 000000000..cc6403a98
--- /dev/null
+++ b/app/src/main/res/drawable-nodpi/theme_preview_system.png
Binary files differ
diff --git a/app/src/main/res/layout/cover_fragment.xml b/app/src/main/res/layout/cover_fragment.xml
index d6664b56c..19f149f2c 100644
--- a/app/src/main/res/layout/cover_fragment.xml
+++ b/app/src/main/res/layout/cover_fragment.xml
@@ -90,6 +90,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
+ android:paddingHorizontal="8dp"
android:background="@drawable/grey_border"
android:clickable="true"
android:focusable="true"
diff --git a/app/src/main/res/layout/edit_tags_dialog.xml b/app/src/main/res/layout/edit_tags_dialog.xml
index 7ad938777..b20facbf0 100644
--- a/app/src/main/res/layout/edit_tags_dialog.xml
+++ b/app/src/main/res/layout/edit_tags_dialog.xml
@@ -7,6 +7,12 @@
android:orientation="vertical"
android:padding="16dp">
+ <CheckBox
+ android:id="@+id/rootFolderCheckbox"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/feed_folders_include_root" />
+
<com.joanzapata.iconify.widget.IconTextView
android:id="@+id/commonTagsInfo"
android:layout_width="match_parent"
@@ -22,12 +28,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
- <CheckBox
- android:id="@+id/rootFolderCheckbox"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/feed_folders_include_root" />
-
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newTagTextInput"
android:layout_width="match_parent"
diff --git a/app/src/main/res/layout/subscription_item.xml b/app/src/main/res/layout/subscription_item.xml
index 50cb9745f..0b689fa28 100644
--- a/app/src/main/res/layout/subscription_item.xml
+++ b/app/src/main/res/layout/subscription_item.xml
@@ -1,64 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:squareImageView="http://schemas.android.com/apk/de.danoeh.antennapod"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:foreground="?attr/selectableItemBackground">
+ android:padding="4dp">
- <de.danoeh.antennapod.ui.common.SquareImageView
- android:id="@+id/imgvCover"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/outerContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/non_square_icon_background"
- android:scaleType="fitCenter"
- squareImageView:direction="width"
- tools:src="@tools:sample/avatars" />
+ android:clickable="false"
+ android:foreground="?attr/selectableItemBackground"
+ app:cardCornerRadius="12dp"
+ app:cardElevation="0dp">
- <com.joanzapata.iconify.widget.IconTextView
- android:id="@+id/txtvTitle"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignStart="@+id/imgvCover"
- android:layout_alignLeft="@+id/imgvCover"
- android:layout_alignTop="@+id/imgvCover"
- android:layout_alignEnd="@+id/imgvCover"
- android:layout_alignRight="@+id/imgvCover"
- android:layout_alignBottom="@+id/imgvCover"
- android:background="@color/non_square_icon_background"
- android:ellipsize="end"
- android:gravity="center"
- android:textColor="?android:attr/textColorPrimary"
- tools:text="@string/app_name" />
-
- <de.danoeh.antennapod.ui.common.TriangleLabelView
- android:id="@+id/triangleCountView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignParentTop="true"
- android:layout_alignParentEnd="true"
- android:layout_alignParentRight="true"
- app:backgroundColor="?attr/colorSecondary"
- app:corner="rightTop"
- app:primaryText="Test"
- app:primaryTextColor="?attr/colorOnSecondary"
- app:primaryTextSize="12sp" />
-
- <FrameLayout
- android:id="@+id/selectView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
-
- <CheckBox
- android:id="@+id/selectCheckBox"
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <androidx.cardview.widget.CardView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="1px"
+ android:clickable="false"
+ app:cardBackgroundColor="@color/non_square_icon_background"
+ app:cardCornerRadius="12dp"
+ app:cardElevation="0dp">
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <de.danoeh.antennapod.ui.common.SquareImageView
+ android:id="@+id/coverImage"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="fitCenter"
+ android:outlineProvider="background"
+ squareImageView:direction="width"
+ tools:src="@tools:sample/avatars" />
+
+ <TextView
+ android:id="@+id/fallbackTitleLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignStart="@+id/coverImage"
+ android:layout_alignLeft="@+id/coverImage"
+ android:layout_alignTop="@+id/coverImage"
+ android:layout_alignEnd="@+id/coverImage"
+ android:layout_alignRight="@+id/coverImage"
+ android:layout_alignBottom="@+id/coverImage"
+ android:background="@color/feed_text_bg"
+ android:gravity="center"
+ android:ellipsize="end"
+ android:padding="6dp"
+ android:textColor="#fff"
+ tools:text="@sample/episodes.json/data/title" />
+
+ <TextView
+ android:id="@+id/countViewPill"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="3"
+ android:layout_alignParentEnd="true"
+ android:textSize="14sp"
+ style="@style/TextPill" />
+
+ </RelativeLayout>
+
+ </androidx.cardview.widget.CardView>
+
+ <TextView
+ android:id="@+id/titleLabel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:gravity="start"
+ android:textColor="?android:attr/textColorPrimary"
+ android:lines="2"
+ tools:text="@sample/episodes.json/data/title" />
+
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/selectContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:minWidth="0dp"
- android:minHeight="0dp"
- android:layout_margin="8dp" />
+ android:clickable="false">
+
+ <CheckBox
+ android:id="@+id/selectCheckBox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="0dp"
+ android:minHeight="0dp"
+ android:layout_margin="8dp" />
+
+ </FrameLayout>
- </FrameLayout>
+ </androidx.cardview.widget.CardView>
-</RelativeLayout>
+</FrameLayout>
diff --git a/app/src/main/res/layout/theme_preference.xml b/app/src/main/res/layout/theme_preference.xml
new file mode 100644
index 000000000..32a7ed1e8
--- /dev/null
+++ b/app/src/main/res/layout/theme_preference.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:background="?android:attr/windowBackground"
+ android:gravity="top"
+ android:padding="8dp">
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/themeSystemCard"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_margin="4dp"
+ android:clickable="true"
+ android:foreground="?android:attr/selectableItemBackground"
+ android:layout_weight="1"
+ app:cardElevation="0dp"
+ app:cardCornerRadius="16dp"
+ app:contentPadding="16dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center">
+
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:adjustViewBounds="true"
+ android:src="@drawable/theme_preview_system" />
+
+ <TextView
+ android:id="@+id/themeSystemRadio"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:text="@string/pref_theme_title_automatic"
+ android:clickable="false" />
+
+ </LinearLayout>
+
+ </androidx.cardview.widget.CardView>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/themeLightCard"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_margin="4dp"
+ android:clickable="true"
+ android:foreground="?android:attr/selectableItemBackground"
+ android:layout_weight="1"
+ app:cardElevation="0dp"
+ app:cardCornerRadius="16dp"
+ app:contentPadding="16dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center">
+
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:adjustViewBounds="true"
+ android:src="@drawable/theme_preview_light" />
+
+ <TextView
+ android:id="@+id/themeLightRadio"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:text="@string/pref_theme_title_light"
+ android:clickable="false" />
+
+ </LinearLayout>
+
+ </androidx.cardview.widget.CardView>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/themeDarkCard"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_margin="4dp"
+ android:clickable="true"
+ android:foreground="?android:attr/selectableItemBackground"
+ android:layout_weight="1"
+ app:cardElevation="0dp"
+ app:cardCornerRadius="16dp"
+ app:contentPadding="16dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center">
+
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:adjustViewBounds="true"
+ android:src="@drawable/theme_preview_dark" />
+
+ <TextView
+ android:id="@+id/themeDarkCardRadio"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:text="@string/pref_theme_title_dark"
+ android:clickable="false" />
+
+ </LinearLayout>
+
+ </androidx.cardview.widget.CardView>
+
+</LinearLayout>
diff --git a/app/src/main/res/menu/downloads_completed.xml b/app/src/main/res/menu/downloads_completed.xml
index 61a0e6578..08179de58 100644
--- a/app/src/main/res/menu/downloads_completed.xml
+++ b/app/src/main/res/menu/downloads_completed.xml
@@ -22,5 +22,10 @@
android:menuCategory="container"
android:icon="@drawable/ic_refresh"
app:showAsAction="always" />
+ <item
+ android:id="@+id/downloads_sort"
+ android:title="@string/sort">
+ <menu></menu>
+ </item>
</menu>
diff --git a/app/src/main/res/menu/queue.xml b/app/src/main/res/menu/queue.xml
index c1c2d982c..e4bb63808 100644
--- a/app/src/main/res/menu/queue.xml
+++ b/app/src/main/res/menu/queue.xml
@@ -24,88 +24,7 @@
<item
android:id="@+id/queue_sort"
android:title="@string/sort">
-
- <menu>
- <item
- android:id="@+id/queue_sort_date"
- android:title="@string/date">
-
- <menu>
- <item
- android:id="@+id/queue_sort_date_asc"
- android:title="@string/sort_old_new"/>
- <item
- android:id="@+id/queue_sort_date_desc"
- android:title="@string/sort_new_old"/>
- </menu>
- </item>
-
- <item
- android:id="@+id/queue_sort_duration"
- android:title="@string/duration">
-
- <menu>
- <item
- android:id="@+id/queue_sort_duration_asc"
- android:title="@string/sort_short_long"/>
- <item
- android:id="@+id/queue_sort_duration_desc"
- android:title="@string/sort_long_short"/>
- </menu>
- </item>
-
- <item
- android:id="@+id/queue_sort_episode_title"
- android:title="@string/episode_title">
-
- <menu>
- <item
- android:id="@+id/queue_sort_episode_title_asc"
- android:title="@string/sort_a_z"/>
- <item
- android:id="@+id/queue_sort_episode_title_desc"
- android:title="@string/sort_z_a"/>
- </menu>
- </item>
-
- <item
- android:id="@+id/queue_sort_feed_title"
- android:title="@string/feed_title">
-
- <menu>
- <item
- android:id="@+id/queue_sort_feed_title_asc"
- android:title="@string/sort_a_z"/>
- <item
- android:id="@+id/queue_sort_feed_title_desc"
- android:title="@string/sort_z_a"/>
- </menu>
- </item>
-
- <item
- android:id="@+id/queue_sort_random"
- android:title="@string/random">
- </item>
-
- <item
- android:id="@+id/queue_sort_smart_shuffle"
- android:title="@string/smart_shuffle">
-
- <menu>
- <item
- android:id="@+id/queue_sort_smart_shuffle_asc"
- android:title="@string/sort_old_new"/>
- <item
- android:id="@+id/queue_sort_smart_shuffle_desc"
- android:title="@string/sort_new_old"/>
- </menu>
- </item>
-
- <item
- android:id="@+id/queue_keep_sorted"
- android:title="@string/keep_sorted"
- android:checkable="true" />
- </menu>
+ <menu></menu>
</item>
<item
diff --git a/app/src/main/res/menu/sort_menu.xml b/app/src/main/res/menu/sort_menu.xml
new file mode 100644
index 000000000..f0a22042b
--- /dev/null
+++ b/app/src/main/res/menu/sort_menu.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/sort_date"
+ android:title="@string/date">
+
+ <menu>
+ <item
+ android:id="@+id/sort_date_asc"
+ android:title="@string/sort_old_new"/>
+ <item
+ android:id="@+id/sort_date_desc"
+ android:title="@string/sort_new_old"/>
+ </menu>
+ </item>
+
+ <item
+ android:id="@+id/sort_duration"
+ android:title="@string/duration">
+
+ <menu>
+ <item
+ android:id="@+id/sort_duration_asc"
+ android:title="@string/sort_short_long"/>
+ <item
+ android:id="@+id/sort_duration_desc"
+ android:title="@string/sort_long_short"/>
+ </menu>
+ </item>
+
+ <item
+ android:id="@+id/sort_episode_title"
+ android:title="@string/episode_title">
+
+ <menu>
+ <item
+ android:id="@+id/sort_episode_title_asc"
+ android:title="@string/sort_a_z"/>
+ <item
+ android:id="@+id/sort_episode_title_desc"
+ android:title="@string/sort_z_a"/>
+ </menu>
+ </item>
+
+ <item
+ android:id="@+id/sort_feed_title"
+ android:title="@string/feed_title">
+
+ <menu>
+ <item
+ android:id="@+id/sort_feed_title_asc"
+ android:title="@string/sort_a_z"/>
+ <item
+ android:id="@+id/sort_feed_title_desc"
+ android:title="@string/sort_z_a"/>
+ </menu>
+ </item>
+
+ <item
+ android:id="@+id/sort_random"
+ android:title="@string/random">
+ </item>
+
+ <item
+ android:id="@+id/sort_smart_shuffle"
+ android:title="@string/smart_shuffle">
+
+ <menu>
+ <item
+ android:id="@+id/sort_smart_shuffle_asc"
+ android:title="@string/sort_old_new"/>
+ <item
+ android:id="@+id/sort_smart_shuffle_desc"
+ android:title="@string/sort_new_old"/>
+ </menu>
+ </item>
+ <item
+ android:id="@+id/keep_sorted"
+ android:title="@string/keep_sorted"
+ android:checkable="true" />
+
+</menu>
diff --git a/app/src/main/res/xml/preferences_user_interface.xml b/app/src/main/res/xml/preferences_user_interface.xml
index f11b89be7..ed3f5777a 100644
--- a/app/src/main/res/xml/preferences_user_interface.xml
+++ b/app/src/main/res/xml/preferences_user_interface.xml
@@ -4,13 +4,13 @@
xmlns:search="http://schemas.android.com/apk/com.bytehamster.lib.preferencesearch">
<PreferenceCategory android:title="@string/appearance">
- <de.danoeh.antennapod.preferences.MaterialListPreference
- android:entryValues="@array/theme_values"
- android:entries="@array/theme_options"
- android:title="@string/pref_set_theme_title"
- android:key="prefTheme"
- android:summary="@string/pref_set_theme_sum"
- android:defaultValue="system"/>
+ <de.danoeh.antennapod.preferences.ThemePreference
+ android:key="prefTheme" />
+ <SwitchPreferenceCompat
+ android:title="@string/pref_black_theme_title"
+ android:key="prefThemeBlack"
+ android:summary="@string/pref_black_theme_message"
+ android:defaultValue="false" />
<SwitchPreferenceCompat
android:title="@string/pref_tinted_theme_title"
android:key="prefTintedColors"