summaryrefslogtreecommitdiff
path: root/app/src/main/java/de
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/de')
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java28
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java37
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/IntraFeedSortDialog.java68
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/ItemFilterDialog.java38
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/ItemSortDialog.java104
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java13
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/SubscriptionsFilterDialog.java117
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java73
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java41
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java58
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java33
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java35
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java126
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/InboxFragment.java57
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/MenuItemToSortOrderConverter.java44
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java112
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java18
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java95
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java86
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java17
-rw-r--r--app/src/main/java/de/danoeh/antennapod/ui/home/HomeFragment.java21
-rw-r--r--app/src/main/java/de/danoeh/antennapod/ui/home/sections/EchoSection.java26
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java10
28 files changed, 691 insertions, 583 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
index c5d656aa0..031117170 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
@@ -36,6 +36,7 @@ import de.danoeh.antennapod.core.feed.FeedUrlNotFoundException;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceInterface;
import de.danoeh.antennapod.core.util.DownloadErrorLabel;
+import de.danoeh.antennapod.databinding.EditTextDialogBinding;
import de.danoeh.antennapod.databinding.OnlinefeedviewHeaderBinding;
import de.danoeh.antennapod.event.EpisodeDownloadEvent;
import de.danoeh.antennapod.event.FeedListUpdateEvent;
@@ -95,7 +96,7 @@ import java.util.Map;
public class OnlineFeedViewActivity extends AppCompatActivity {
public static final String ARG_FEEDURL = "arg.feedurl";
- // Optional argument: specify a title for the actionbar.
+ public static final String ARG_WAS_MANUAL_URL = "manual_url";
private static final int RESULT_ERROR = 2;
private static final String TAG = "OnlineFeedViewActivity";
private static final String PREFS = "OnlineFeedViewActivityPreferences";
@@ -598,7 +599,10 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
builder.setMessage(R.string.download_error_error_unknown);
}
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.cancel());
- builder.setOnDismissListener(dialog -> {
+ if (getIntent().getBooleanExtra(ARG_WAS_MANUAL_URL, false)) {
+ builder.setNeutralButton(R.string.edit_url_menu, (dialog, which) -> editUrl());
+ }
+ builder.setOnCancelListener(dialog -> {
setResult(RESULT_ERROR);
finish();
});
@@ -609,6 +613,26 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
}
}
+ private void editUrl() {
+ MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
+ builder.setTitle(R.string.edit_url_menu);
+ final EditTextDialogBinding dialogBinding = EditTextDialogBinding.inflate(getLayoutInflater());
+ if (downloader != null) {
+ dialogBinding.urlEditText.setText(downloader.getDownloadRequest().getSource());
+ }
+ builder.setView(dialogBinding.getRoot());
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
+ setLoadingLayout();
+ lookupUrlAndDownload(dialogBinding.urlEditText.getText().toString());
+ });
+ builder.setNegativeButton(R.string.cancel_label, (dialog1, which) -> dialog1.cancel());
+ builder.setOnCancelListener(dialog1 -> {
+ setResult(RESULT_ERROR);
+ finish();
+ });
+ builder.show();
+ }
+
@Subscribe(threadMode = ThreadMode.MAIN)
public void playbackStateChanged(PlayerStatusEvent event) {
boolean isPlayingPreview =
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java
index 10a41057c..3f1c17cdc 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java
@@ -6,7 +6,9 @@ import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.os.Environment;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.Menu;
@@ -45,6 +47,7 @@ import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
/**
* Activity for Opml Import.
@@ -140,15 +143,6 @@ public class OpmlImportActivity extends AppCompatActivity {
return;
}
this.uri = uri;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
- && uri.toString().contains(Environment.getExternalStorageDirectory().toString())) {
- int permission = ActivityCompat.checkSelfPermission(this,
- android.Manifest.permission.READ_EXTERNAL_STORAGE);
- if (permission != PackageManager.PERMISSION_GRANTED) {
- requestPermission();
- return;
- }
- }
startImport();
}
@@ -244,12 +238,29 @@ public class OpmlImportActivity extends AppCompatActivity {
getTitleList());
viewBinding.feedlist.setAdapter(listAdapter);
}, e -> {
+ Log.d(TAG, Log.getStackTraceString(e));
+ String message = e.getMessage() == null ? "" : e.getMessage();
+ if (message.toLowerCase(Locale.ROOT).contains("permission")
+ && Build.VERSION.SDK_INT >= 23) {
+ int permission = ActivityCompat.checkSelfPermission(this,
+ android.Manifest.permission.READ_EXTERNAL_STORAGE);
+ if (permission != PackageManager.PERMISSION_GRANTED) {
+ requestPermission();
+ return;
+ }
+ }
viewBinding.progressBar.setVisibility(View.GONE);
MaterialAlertDialogBuilder alert = new MaterialAlertDialogBuilder(this);
alert.setTitle(R.string.error_label);
- alert.setMessage(getString(R.string.opml_reader_error) + e.getMessage());
- alert.setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss());
- alert.create().show();
+ String userReadable = getString(R.string.opml_reader_error);
+ String details = e.getMessage();
+ String total = userReadable + "\n\n" + details;
+ SpannableString errorMessage = new SpannableString(total);
+ errorMessage.setSpan(new ForegroundColorSpan(0x88888888),
+ userReadable.length(), total.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ alert.setMessage(errorMessage);
+ alert.setPositiveButton(android.R.string.ok, (dialog, which) -> finish());
+ alert.show();
});
}
}
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 e3473937e..fc371090e 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java
@@ -567,7 +567,8 @@ public class VideoplayerActivity extends CastEnabledActivity implements SeekBar.
menu.findItem(R.id.disable_sleeptimer_item).setVisible(controller.sleepTimerActive());
menu.findItem(R.id.player_switch_to_audio_only).setVisible(true);
- menu.findItem(R.id.audio_controls).setIcon(R.drawable.ic_sliders);
+
+ menu.findItem(R.id.audio_controls).setVisible(controller.getAudioTracks().size() >= 2);
menu.findItem(R.id.playback_speed).setVisible(true);
menu.findItem(R.id.player_show_chapters).setVisible(true);
return true;
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
index 8d220c90d..a304ead3c 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
@@ -261,7 +261,7 @@ public class NavListAdapter extends RecyclerView.Adapter<NavListAdapter.Holder>
int spaceUsed = itemAccess.getNumberOfDownloadedItems()
- itemAccess.getReclaimableItems();
if (epCacheSize > 0 && spaceUsed >= epCacheSize) {
- holder.count.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_disc_full, 0);
+ holder.count.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_disc_alert, 0);
holder.count.setVisibility(View.VISIBLE);
holder.count.setOnClickListener(v ->
new MaterialAlertDialogBuilder(context)
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/IntraFeedSortDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/IntraFeedSortDialog.java
deleted file mode 100644
index dc8cf65ba..000000000
--- a/app/src/main/java/de/danoeh/antennapod/dialog/IntraFeedSortDialog.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package de.danoeh.antennapod.dialog;
-
-import android.content.Context;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.model.feed.SortOrder;
-
-public abstract class IntraFeedSortDialog {
-
- @Nullable
- protected SortOrder currentSortOrder;
- @NonNull
- protected Context context;
-
- private final String[] sortItems;
- private final SortOrder[] sortValues;
-
- public IntraFeedSortDialog(@NonNull Context context, @Nullable SortOrder sortOrder, @NonNull boolean isLocalFeed) {
- this.context = context;
- this.currentSortOrder = sortOrder;
-
- if (isLocalFeed) {
- sortItems = context.getResources().getStringArray(R.array.local_feed_episodes_sort_options);
- final String[] localSortStringValues =
- context.getResources().getStringArray(R.array.local_feed_episodes_sort_values);
- sortValues = SortOrder.valuesOf(localSortStringValues);
- } else {
- sortItems = context.getResources().getStringArray(R.array.feed_episodes_sort_options);
- final String[] commonSortStringValues =
- context.getResources().getStringArray(R.array.feed_episodes_sort_values);
- sortValues = SortOrder.valuesOf(commonSortStringValues);
- }
- }
-
- public void openDialog() {
- int idxCurrentSort = getCurrentSortOrderIndex();
-
- MaterialAlertDialogBuilder builder =
- new MaterialAlertDialogBuilder(context)
- .setTitle(R.string.sort)
- .setSingleChoiceItems(sortItems, idxCurrentSort, (dialog, idxNewSort) -> {
- updateSort(sortValues[idxNewSort]);
- dialog.dismiss();
- })
- .setNegativeButton(R.string.cancel_label, null);
- builder.create().show();
- }
-
- /**
- * Retrieves index of currentSortOrder index in values array.
- * @return if currentSortOrder is found in array - returns index of that element,
- * otherwise returns 0, the default sort option;
- */
- private int getCurrentSortOrderIndex() {
- for (int i = 0; i < sortValues.length; i++) {
- if (currentSortOrder == sortValues[i]) {
- return i;
- }
- }
- return 0;
- }
-
- protected abstract void updateSort(@NonNull SortOrder sortOrder);
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ItemFilterDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ItemFilterDialog.java
index 92c143992..359c513af 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/ItemFilterDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/ItemFilterDialog.java
@@ -18,11 +18,13 @@ import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.button.MaterialButtonToggleGroup;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItemFilterGroup;
+import de.danoeh.antennapod.databinding.FilterDialogBinding;
import de.danoeh.antennapod.databinding.FilterDialogRowBinding;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
@@ -36,24 +38,36 @@ public abstract class ItemFilterDialog extends BottomSheetDialogFragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.filter_dialog, null, false);
- rows = layout.findViewById(R.id.filter_rows);
+ FilterDialogBinding binding = FilterDialogBinding.bind(layout);
+ rows = binding.filterRows;
FeedItemFilter filter = (FeedItemFilter) getArguments().getSerializable(ARGUMENT_FILTER);
+ //add filter rows
for (FeedItemFilterGroup item : FeedItemFilterGroup.values()) {
- FilterDialogRowBinding binding = FilterDialogRowBinding.inflate(inflater);
- binding.getRoot().addOnButtonCheckedListener(
+ FilterDialogRowBinding rowBinding = FilterDialogRowBinding.inflate(inflater);
+ rowBinding.getRoot().addOnButtonCheckedListener(
(group, checkedId, isChecked) -> onFilterChanged(getNewFilterValues()));
- binding.filterButton1.setText(item.values[0].displayName);
- binding.filterButton1.setTag(item.values[0].filterId);
- binding.filterButton2.setText(item.values[1].displayName);
- binding.filterButton2.setTag(item.values[1].filterId);
- binding.filterButton1.setMaxLines(3);
- binding.filterButton1.setSingleLine(false);
- binding.filterButton2.setMaxLines(3);
- binding.filterButton2.setSingleLine(false);
- rows.addView(binding.getRoot());
+ rowBinding.filterButton1.setText(item.values[0].displayName);
+ rowBinding.filterButton1.setTag(item.values[0].filterId);
+ rowBinding.filterButton2.setText(item.values[1].displayName);
+ rowBinding.filterButton2.setTag(item.values[1].filterId);
+ rowBinding.filterButton1.setMaxLines(3);
+ rowBinding.filterButton1.setSingleLine(false);
+ rowBinding.filterButton2.setMaxLines(3);
+ rowBinding.filterButton2.setSingleLine(false);
+ rows.addView(rowBinding.getRoot(), rows.getChildCount() - 1);
}
+ binding.confirmFiltermenu.setOnClickListener(view1 -> dismiss());
+ binding.resetFiltermenu.setOnClickListener(view1 -> {
+ onFilterChanged(Collections.emptySet());
+ for (int i = 0; i < rows.getChildCount(); i++) {
+ if (rows.getChildAt(i) instanceof MaterialButtonToggleGroup) {
+ ((MaterialButtonToggleGroup) rows.getChildAt(i)).clearChecked();
+ }
+ }
+ });
+
for (String filterId : filter.getValues()) {
if (!TextUtils.isEmpty(filterId)) {
Button button = layout.findViewWithTag(filterId);
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ItemSortDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ItemSortDialog.java
new file mode 100644
index 000000000..cd6cc4b0a
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/ItemSortDialog.java
@@ -0,0 +1,104 @@
+package de.danoeh.antennapod.dialog;
+
+import android.app.Dialog;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetDialog;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.databinding.SortDialogBinding;
+import de.danoeh.antennapod.databinding.SortDialogItemActiveBinding;
+import de.danoeh.antennapod.databinding.SortDialogItemBinding;
+import de.danoeh.antennapod.model.feed.SortOrder;
+
+public class ItemSortDialog extends BottomSheetDialogFragment {
+ protected SortOrder sortOrder;
+ protected SortDialogBinding viewBinding;
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ viewBinding = SortDialogBinding.inflate(inflater);
+ populateList();
+ viewBinding.keepSortedCheckbox.setOnCheckedChangeListener(
+ (buttonView, isChecked) -> ItemSortDialog.this.onSelectionChanged());
+ return viewBinding.getRoot();
+ }
+
+ private void populateList() {
+ viewBinding.gridLayout.removeAllViews();
+ onAddItem(R.string.episode_title, SortOrder.EPISODE_TITLE_A_Z, SortOrder.EPISODE_TITLE_Z_A, true);
+ onAddItem(R.string.feed_title, SortOrder.FEED_TITLE_A_Z, SortOrder.FEED_TITLE_Z_A, true);
+ onAddItem(R.string.duration, SortOrder.DURATION_SHORT_LONG, SortOrder.DURATION_LONG_SHORT, true);
+ onAddItem(R.string.date, SortOrder.DATE_OLD_NEW, SortOrder.DATE_NEW_OLD, false);
+ onAddItem(R.string.size, SortOrder.SIZE_SMALL_LARGE, SortOrder.SIZE_LARGE_SMALL, false);
+ onAddItem(R.string.filename, SortOrder.EPISODE_FILENAME_A_Z, SortOrder.EPISODE_FILENAME_Z_A, true);
+ onAddItem(R.string.random, SortOrder.RANDOM, SortOrder.RANDOM, true);
+ onAddItem(R.string.smart_shuffle, SortOrder.SMART_SHUFFLE_OLD_NEW, SortOrder.SMART_SHUFFLE_NEW_OLD, false);
+ }
+
+ protected void onAddItem(int title, SortOrder ascending, SortOrder descending, boolean ascendingIsDefault) {
+ if (sortOrder == ascending || sortOrder == descending) {
+ SortDialogItemActiveBinding item = SortDialogItemActiveBinding.inflate(
+ getLayoutInflater(), viewBinding.gridLayout, false);
+ SortOrder other;
+ if (ascending == descending) {
+ item.button.setText(title);
+ other = ascending;
+ } else if (sortOrder == ascending) {
+ item.button.setText(getString(title) + "\u00A0▲");
+ other = descending;
+ } else {
+ item.button.setText(getString(title) + "\u00A0▼");
+ other = ascending;
+ }
+ item.button.setOnClickListener(v -> {
+ sortOrder = other;
+ populateList();
+ onSelectionChanged();
+ });
+ viewBinding.gridLayout.addView(item.getRoot());
+ } else {
+ SortDialogItemBinding item = SortDialogItemBinding.inflate(
+ getLayoutInflater(), viewBinding.gridLayout, false);
+ item.button.setText(title);
+ item.button.setOnClickListener(v -> {
+ sortOrder = ascendingIsDefault ? ascending : descending;
+ populateList();
+ onSelectionChanged();
+ });
+ viewBinding.gridLayout.addView(item.getRoot());
+ }
+ }
+
+ protected void onSelectionChanged() {
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ Dialog dialog = super.onCreateDialog(savedInstanceState);
+ dialog.setOnShowListener(dialogInterface -> {
+ BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialogInterface;
+ setupFullHeight(bottomSheetDialog);
+ });
+ return dialog;
+ }
+
+ private void setupFullHeight(BottomSheetDialog bottomSheetDialog) {
+ FrameLayout bottomSheet = bottomSheetDialog.findViewById(R.id.design_bottom_sheet);
+ if (bottomSheet != null) {
+ BottomSheetBehavior<FrameLayout> behavior = BottomSheetBehavior.from(bottomSheet);
+ ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
+ bottomSheet.setLayoutParams(layoutParams);
+ behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
+ }
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java
index a87dccdf5..009f33fe2 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java
@@ -10,9 +10,7 @@ import androidx.appcompat.app.AlertDialog;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import androidx.fragment.app.DialogFragment;
import android.widget.Button;
-import android.widget.CheckBox;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import java.util.List;
@@ -37,12 +35,10 @@ public class PlaybackControlsDialog extends DialogFragment {
controller = new PlaybackController(getActivity()) {
@Override
public void loadMediaInfo() {
- setupUi();
setupAudioTracks();
}
};
controller.init();
- setupUi();
}
@Override
@@ -62,15 +58,6 @@ public class PlaybackControlsDialog extends DialogFragment {
return dialog;
}
- private void setupUi() {
- final CheckBox skipSilence = dialog.findViewById(R.id.skipSilence);
- skipSilence.setChecked(UserPreferences.isSkipSilence());
- skipSilence.setOnCheckedChangeListener((buttonView, isChecked) -> {
- UserPreferences.setSkipSilence(isChecked);
- controller.setSkipSilence(isChecked);
- });
- }
-
private void setupAudioTracks() {
List<String> audioTracks = controller.getAudioTracks();
int selectedAudioTrack = controller.getSelectedAudioTrack();
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/SubscriptionsFilterDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SubscriptionsFilterDialog.java
index cf77c2838..929e6b1ad 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/SubscriptionsFilterDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/SubscriptionsFilterDialog.java
@@ -1,42 +1,49 @@
package de.danoeh.antennapod.dialog;
-import android.content.Context;
+import android.app.Dialog;
+import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.FrameLayout;
import android.widget.LinearLayout;
-
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetDialog;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.button.MaterialButtonToggleGroup;
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
-import org.greenrobot.eventbus.EventBus;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.SubscriptionsFilterGroup;
+import de.danoeh.antennapod.databinding.FilterDialogBinding;
import de.danoeh.antennapod.databinding.FilterDialogRowBinding;
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.model.feed.SubscriptionsFilter;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
+import org.greenrobot.eventbus.EventBus;
-public class SubscriptionsFilterDialog {
- public static void showDialog(Context context) {
- SubscriptionsFilter subscriptionsFilter = UserPreferences.getSubscriptionsFilter();
- final Set<String> filterValues = new HashSet<>(Arrays.asList(subscriptionsFilter.getValues()));
- MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context);
- builder.setTitle(context.getString(R.string.pref_filter_feed_title));
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
- LayoutInflater inflater = LayoutInflater.from(context);
- View layout = inflater.inflate(R.layout.filter_dialog, null, false);
- LinearLayout rows = layout.findViewById(R.id.filter_rows);
- builder.setView(layout);
+public class SubscriptionsFilterDialog extends BottomSheetDialogFragment {
+ private LinearLayout rows;
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ SubscriptionsFilter subscriptionsFilter = UserPreferences.getSubscriptionsFilter();
+ FilterDialogBinding dialogBinding = FilterDialogBinding.inflate(inflater);
+ rows = dialogBinding.filterRows;
for (SubscriptionsFilterGroup item : SubscriptionsFilterGroup.values()) {
FilterDialogRowBinding binding = FilterDialogRowBinding.inflate(inflater);
+ binding.getRoot().addOnButtonCheckedListener(
+ (group, checkedId, isChecked) -> updateFilter(getFilterValues()));
binding.buttonGroup.setWeightSum(item.values.length);
binding.filterButton1.setText(item.values[0].displayName);
binding.filterButton1.setTag(item.values[0].filterId);
@@ -50,38 +57,72 @@ public class SubscriptionsFilterDialog {
binding.filterButton1.setSingleLine(false);
binding.filterButton2.setMaxLines(3);
binding.filterButton2.setSingleLine(false);
- rows.addView(binding.getRoot());
+ rows.addView(binding.getRoot(), rows.getChildCount() - 1);
}
+ final Set<String> filterValues = new HashSet<>(Arrays.asList(subscriptionsFilter.getValues()));
for (String filterId : filterValues) {
if (!TextUtils.isEmpty(filterId)) {
- Button button = layout.findViewWithTag(filterId);
+ Button button = dialogBinding.getRoot().findViewWithTag(filterId);
if (button != null) {
((MaterialButtonToggleGroup) button.getParent()).check(button.getId());
}
}
}
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- filterValues.clear();
+ dialogBinding.confirmFiltermenu.setOnClickListener(view -> {
+ updateFilter(getFilterValues());
+ dismiss();
+ });
+ dialogBinding.resetFiltermenu.setOnClickListener(view -> {
+ updateFilter(Collections.emptySet());
for (int i = 0; i < rows.getChildCount(); i++) {
- if (!(rows.getChildAt(i) instanceof MaterialButtonToggleGroup)) {
- continue;
- }
- MaterialButtonToggleGroup group = (MaterialButtonToggleGroup) rows.getChildAt(i);
- if (group.getCheckedButtonId() == View.NO_ID) {
- continue;
- }
- String tag = (String) group.findViewById(group.getCheckedButtonId()).getTag();
- if (tag == null) { // Clear buttons use no tag
- continue;
+ if (rows.getChildAt(i) instanceof MaterialButtonToggleGroup) {
+ ((MaterialButtonToggleGroup) rows.getChildAt(i)).clearChecked();
}
- filterValues.add(tag);
}
- updateFilter(filterValues);
});
- builder.setNegativeButton(R.string.cancel_label, null);
- builder.show();
+ return dialogBinding.getRoot();
+ }
+
+ private Set<String> getFilterValues() {
+ Set<String> filterValues = new HashSet<>();
+ for (int i = 0; i < rows.getChildCount(); i++) {
+ if (!(rows.getChildAt(i) instanceof MaterialButtonToggleGroup)) {
+ continue;
+ }
+ MaterialButtonToggleGroup group = (MaterialButtonToggleGroup) rows.getChildAt(i);
+ if (group.getCheckedButtonId() == View.NO_ID) {
+ continue;
+ }
+ String tag = (String) group.findViewById(group.getCheckedButtonId()).getTag();
+ if (tag == null) { // Clear buttons use no tag
+ continue;
+ }
+ filterValues.add(tag);
+ }
+ return filterValues;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ Dialog dialog = super.onCreateDialog(savedInstanceState);
+ dialog.setOnShowListener(dialogInterface -> {
+ BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialogInterface;
+ setupFullHeight(bottomSheetDialog);
+ });
+ return dialog;
+ }
+
+ private void setupFullHeight(BottomSheetDialog bottomSheetDialog) {
+ FrameLayout bottomSheet = bottomSheetDialog.findViewById(R.id.design_bottom_sheet);
+ if (bottomSheet != null) {
+ BottomSheetBehavior<FrameLayout> behavior = BottomSheetBehavior.from(bottomSheet);
+ ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
+ bottomSheet.setLayoutParams(layoutParams);
+ behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
+ }
}
private static void updateFilter(Set<String> filterValues) {
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 0367e717b..8de7dce04 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
@@ -6,6 +6,8 @@ import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.CheckBox;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
@@ -94,6 +96,13 @@ public class VariableSpeedDialog extends BottomSheetDialogFragment {
addCurrentSpeedChip.setOnCloseIconClickListener(v -> addCurrentSpeed());
addCurrentSpeedChip.setCloseIconContentDescription(getString(R.string.add_preset));
addCurrentSpeedChip.setOnClickListener(v -> addCurrentSpeed());
+
+ final CheckBox skipSilence = root.findViewById(R.id.skipSilence);
+ skipSilence.setChecked(UserPreferences.isSkipSilence());
+ skipSilence.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ UserPreferences.setSkipSilence(isChecked);
+ controller.setSkipSilence(isChecked);
+ });
return root;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
index 29be41727..20cdd2718 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
@@ -147,6 +147,7 @@ public class AddFeedFragment extends Fragment {
private void addUrl(String url) {
Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);
intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, url);
+ intent.putExtra(OnlineFeedViewActivity.ARG_WAS_MANUAL_URL, true);
startActivity(intent);
}
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 7061a69f3..ab5039ec2 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -1,20 +1,23 @@
package de.danoeh.antennapod.fragment;
-import android.content.Context;
-import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.dialog.AllEpisodesFilterDialog;
+import de.danoeh.antennapod.dialog.ItemSortDialog;
+import de.danoeh.antennapod.event.FeedListUpdateEvent;
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 org.apache.commons.lang3.StringUtils;
+import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.ArrayList;
@@ -26,48 +29,33 @@ import java.util.List;
*/
public class AllEpisodesFragment extends EpisodesListFragment {
public static final String TAG = "EpisodesFragment";
- private static final String PREF_NAME = "PrefAllEpisodesFragment";
- private static final String PREF_FILTER = "filter";
- public static final String PREF_SORT = "prefEpisodesSort";
- private SharedPreferences prefs;
+ public static final String PREF_NAME = "PrefAllEpisodesFragment";
@NonNull
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View root = super.onCreateView(inflater, container, savedInstanceState);
toolbar.inflateMenu(R.menu.episodes);
- inflateSortMenu();
toolbar.setTitle(R.string.episodes_label);
updateToolbar();
updateFilterUi();
- prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
txtvInformation.setOnClickListener(
v -> AllEpisodesFilterDialog.newInstance(getFilter()).show(getChildFragmentManager(), null));
return root;
}
- private void inflateSortMenu() {
- MenuItem sortItem = toolbar.getMenu().findItem(R.id.episodes_sort);
- getActivity().getMenuInflater().inflate(R.menu.sort_menu, sortItem.getSubMenu());
-
- // Remove the sorting options that are not needed in this fragment
- toolbar.getMenu().findItem(R.id.sort_episode_title).setVisible(false);
- toolbar.getMenu().findItem(R.id.sort_feed_title).setVisible(false);
- toolbar.getMenu().findItem(R.id.sort_random).setVisible(false);
- toolbar.getMenu().findItem(R.id.sort_smart_shuffle).setVisible(false);
- toolbar.getMenu().findItem(R.id.keep_sorted).setVisible(false);
- }
-
@NonNull
@Override
protected List<FeedItem> loadData() {
- return DBReader.getEpisodes(0, page * EPISODES_PER_PAGE, getFilter(), getSortOrder());
+ return DBReader.getEpisodes(0, page * EPISODES_PER_PAGE, getFilter(),
+ UserPreferences.getAllEpisodesSortOrder());
}
@NonNull
@Override
protected List<FeedItem> loadMoreData(int page) {
- return DBReader.getEpisodes((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE, getFilter(), getSortOrder());
+ return DBReader.getEpisodes((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE, getFilter(),
+ UserPreferences.getAllEpisodesSortOrder());
}
@Override
@@ -77,8 +65,7 @@ public class AllEpisodesFragment extends EpisodesListFragment {
@Override
protected FeedItemFilter getFilter() {
- SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
- return new FeedItemFilter(prefs.getString(PREF_FILTER, ""));
+ return new FeedItemFilter(UserPreferences.getPrefFilterAllEpisodes());
}
@Override
@@ -108,24 +95,16 @@ public class AllEpisodesFragment extends EpisodesListFragment {
}
onFilterChanged(new AllEpisodesFilterDialog.AllEpisodesFilterChangedEvent(new HashSet<>(filter)));
return true;
- } else {
- SortOrder sortOrder = MenuItemToSortOrderConverter.convert(item);
- if (sortOrder != null) {
- saveSortOrderAndRefresh(sortOrder);
- return true;
- }
+ } else if (item.getItemId() == R.id.episodes_sort) {
+ new AllEpisodesSortDialog().show(getChildFragmentManager().beginTransaction(), "SortDialog");
+ return true;
}
return false;
}
- private void saveSortOrderAndRefresh(SortOrder type) {
- prefs.edit().putString(PREF_SORT, "" + type.code).apply();
- loadItems();
- }
-
@Subscribe
public void onFilterChanged(AllEpisodesFilterDialog.AllEpisodesFilterChangedEvent event) {
- prefs.edit().putString(PREF_FILTER, StringUtils.join(event.filterValues, ",")).apply();
+ UserPreferences.setPrefFilterAllEpisodes(StringUtils.join(event.filterValues, ","));
updateFilterUi();
page = 1;
loadItems();
@@ -144,7 +123,25 @@ public class AllEpisodesFragment extends EpisodesListFragment {
getFilter().showIsFavorite ? R.drawable.ic_star : R.drawable.ic_star_border);
}
- private SortOrder getSortOrder() {
- return SortOrder.fromCodeString(prefs.getString(PREF_SORT, "" + SortOrder.DATE_NEW_OLD.code));
+ public static class AllEpisodesSortDialog extends ItemSortDialog {
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ sortOrder = UserPreferences.getAllEpisodesSortOrder();
+ }
+
+ @Override
+ protected void onAddItem(int title, SortOrder ascending, SortOrder descending, boolean ascendingIsDefault) {
+ if (ascending == SortOrder.DATE_OLD_NEW || ascending == SortOrder.DURATION_SHORT_LONG) {
+ super.onAddItem(title, ascending, descending, ascendingIsDefault);
+ }
+ }
+
+ @Override
+ protected void onSelectionChanged() {
+ super.onSelectionChanged();
+ UserPreferences.setAllEpisodesSortOrder(sortOrder);
+ EventBus.getDefault().post(new FeedListUpdateEvent(0));
+ }
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java
index f2a53ab7e..8b25c0e6a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java
@@ -15,25 +15,16 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.google.android.material.appbar.MaterialToolbar;
import androidx.cardview.widget.CardView;
import androidx.fragment.app.Fragment;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
+import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.elevation.SurfaceColors;
-import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
-import de.danoeh.antennapod.core.util.playback.PlaybackController;
-import de.danoeh.antennapod.dialog.MediaPlayerErrorDialog;
-import de.danoeh.antennapod.event.playback.BufferUpdateEvent;
-import de.danoeh.antennapod.event.playback.PlaybackServiceEvent;
-import de.danoeh.antennapod.event.PlayerErrorEvent;
-import de.danoeh.antennapod.event.playback.SleepTimerUpdatedEvent;
-import de.danoeh.antennapod.event.playback.SpeedChangedEvent;
-import de.danoeh.antennapod.playback.cast.CastEnabledActivity;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@@ -44,23 +35,31 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.event.FavoritesEvent;
-import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
-import de.danoeh.antennapod.model.feed.Chapter;
-import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
-import de.danoeh.antennapod.model.feed.FeedItem;
-import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils;
-import de.danoeh.antennapod.storage.preferences.UserPreferences;
+import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.core.util.ChapterUtils;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.TimeSpeedConverter;
-import de.danoeh.antennapod.model.playback.Playable;
-import de.danoeh.antennapod.dialog.PlaybackControlsDialog;
+import de.danoeh.antennapod.core.util.playback.PlaybackController;
+import de.danoeh.antennapod.dialog.MediaPlayerErrorDialog;
import de.danoeh.antennapod.dialog.SkipPreferenceDialog;
import de.danoeh.antennapod.dialog.SleepTimerDialog;
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
+import de.danoeh.antennapod.event.FavoritesEvent;
+import de.danoeh.antennapod.event.PlayerErrorEvent;
+import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
+import de.danoeh.antennapod.event.playback.BufferUpdateEvent;
+import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
+import de.danoeh.antennapod.event.playback.PlaybackServiceEvent;
+import de.danoeh.antennapod.event.playback.SleepTimerUpdatedEvent;
+import de.danoeh.antennapod.event.playback.SpeedChangedEvent;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
+import de.danoeh.antennapod.model.feed.Chapter;
+import de.danoeh.antennapod.model.feed.FeedItem;
+import de.danoeh.antennapod.model.feed.FeedMedia;
+import de.danoeh.antennapod.model.playback.Playable;
+import de.danoeh.antennapod.playback.cast.CastEnabledActivity;
+import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.ui.common.PlaybackSpeedIndicatorView;
import de.danoeh.antennapod.view.ChapterSeekBar;
import de.danoeh.antennapod.view.PlayButton;
@@ -503,10 +502,6 @@ public class AudioPlayerFragment extends Fragment implements
if (itemId == R.id.disable_sleeptimer_item || itemId == R.id.set_sleeptimer_item) {
new SleepTimerDialog().show(getChildFragmentManager(), "SleepTimerDialog");
return true;
- } else if (itemId == R.id.audio_controls) {
- PlaybackControlsDialog dialog = PlaybackControlsDialog.newInstance();
- dialog.show(getChildFragmentManager(), "playback_controls");
- return true;
} else if (itemId == R.id.open_feed_item) {
if (feedItem != null) {
Intent intent = MainActivity.getIntentToOpenFeed(getContext(), feedItem.getFeedId());
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 730a39189..ec7a35466 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
@@ -4,16 +4,14 @@ 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;
import android.widget.ProgressBar;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.google.android.material.appbar.MaterialToolbar;
import androidx.fragment.app.Fragment;
+import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.snackbar.Snackbar;
import com.leinardi.android.speeddial.SpeedDialView;
import de.danoeh.antennapod.R;
@@ -25,6 +23,7 @@ import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.download.FeedUpdateManager;
+import de.danoeh.antennapod.dialog.ItemSortDialog;
import de.danoeh.antennapod.event.EpisodeDownloadEvent;
import de.danoeh.antennapod.event.FeedItemEvent;
import de.danoeh.antennapod.event.PlayerStatusEvent;
@@ -84,8 +83,6 @@ public class CompletedDownloadsFragment extends Fragment
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);
@@ -148,20 +145,6 @@ 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);
- menu.findItem(R.id.sort_size).setVisible(true);
- }
-
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putBoolean(KEY_UP_ARROW, displayUpArrow);
@@ -204,21 +187,13 @@ 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;
- }
+ } else if (item.getItemId() == R.id.downloads_sort) {
+ new DownloadsSortDialog().show(getChildFragmentManager(), "SortDialog");
+ return true;
}
return false;
}
- private void setSortOrder(SortOrder sortOrder) {
- UserPreferences.setDownloadsSortedOrder(sortOrder);
- loadItems();
- }
-
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEventMainThread(EpisodeDownloadEvent event) {
Set<String> newRunningDownloads = new HashSet<>();
@@ -391,4 +366,27 @@ public class CompletedDownloadsFragment extends Fragment
MenuItemUtils.setOnClickListeners(menu, CompletedDownloadsFragment.this::onContextItemSelected);
}
}
+
+ public static class DownloadsSortDialog extends ItemSortDialog {
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ sortOrder = UserPreferences.getDownloadsSortedOrder();
+ }
+
+ @Override
+ protected void onAddItem(int title, SortOrder ascending, SortOrder descending, boolean ascendingIsDefault) {
+ if (ascending == SortOrder.DATE_OLD_NEW || ascending == SortOrder.DURATION_SHORT_LONG
+ || ascending == SortOrder.EPISODE_TITLE_A_Z || ascending == SortOrder.SIZE_SMALL_LARGE) {
+ super.onAddItem(title, ascending, descending, ascendingIsDefault);
+ }
+ }
+
+ @Override
+ protected void onSelectionChanged() {
+ super.onSelectionChanged();
+ UserPreferences.setDownloadsSortedOrder(sortOrder);
+ EventBus.getDefault().post(DownloadLogEvent.listUpdated());
+ }
+ }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
index 00d671d36..0cbc23a56 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
@@ -2,8 +2,6 @@ package de.danoeh.antennapod.fragment;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
@@ -13,6 +11,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
+
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.core.util.Pair;
@@ -20,9 +19,19 @@ import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.snackbar.Snackbar;
import com.leinardi.android.speeddial.SpeedDialView;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.EpisodeItemListAdapter;
@@ -51,13 +60,6 @@ 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.Collections;
-import java.util.List;
/**
* Shows unread or recently published episodes
@@ -77,6 +79,7 @@ public abstract class EpisodesListFragment extends Fragment
EmptyViewHandler emptyView;
SpeedDialView speedDialView;
MaterialToolbar toolbar;
+ SwipeRefreshLayout swipeRefreshLayout;
SwipeActions swipeActions;
private ProgressBar progressBar;
@@ -180,13 +183,9 @@ public abstract class EpisodesListFragment extends Fragment
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}
- SwipeRefreshLayout swipeRefreshLayout = root.findViewById(R.id.swipeRefresh);
+ swipeRefreshLayout = root.findViewById(R.id.swipeRefresh);
swipeRefreshLayout.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance));
- swipeRefreshLayout.setOnRefreshListener(() -> {
- FeedUpdateManager.runOnceOrAsk(requireContext());
- new Handler(Looper.getMainLooper()).postDelayed(() -> swipeRefreshLayout.setRefreshing(false),
- getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms));
- });
+ swipeRefreshLayout.setOnRefreshListener(() -> FeedUpdateManager.runOnceOrAsk(requireContext()));
listAdapter = new EpisodeItemListAdapter((MainActivity) getActivity()) {
@Override
@@ -456,9 +455,7 @@ public abstract class EpisodesListFragment extends Fragment
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEventMainThread(FeedUpdateRunningEvent event) {
- if (toolbar.getMenu().findItem(R.id.refresh_item) != null) {
- MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(), R.id.refresh_item, event.isFeedUpdateRunning);
- }
+ swipeRefreshLayout.setRefreshing(event.isFeedUpdateRunning);
}
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java
index b4fa77c75..f62bdaf84 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java
@@ -22,25 +22,24 @@ import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import androidx.appcompat.content.res.AppCompatResources;
-import com.google.android.material.appbar.MaterialToolbar;
import androidx.documentfile.provider.DocumentFile;
import androidx.fragment.app.Fragment;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
+import com.google.android.material.appbar.MaterialToolbar;
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
-import com.joanzapata.iconify.Iconify;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.util.IntentUtils;
+import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
import de.danoeh.antennapod.dialog.EditUrlSettingsDialog;
-import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedFunding;
import de.danoeh.antennapod.ui.glide.FastBlurTransformation;
@@ -228,7 +227,8 @@ public class FeedInfoFragment extends Fragment implements MaterialToolbar.OnMenu
txtvAuthorHeader.setText(feed.getAuthor());
}
- txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}");
+ txtvUrl.setText(feed.getDownload_url());
+ txtvUrl.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_paperclip, 0);
if (feed.getPaymentLinks() == null || feed.getPaymentLinks().size() == 0) {
lblSupport.setVisibility(View.GONE);
@@ -263,7 +263,6 @@ public class FeedInfoFragment extends Fragment implements MaterialToolbar.OnMenu
txtvFundingUrl.setText(str.toString());
}
- Iconify.addIcons(txtvUrl);
refreshToolbarState();
}
@@ -290,9 +289,11 @@ public class FeedInfoFragment extends Fragment implements MaterialToolbar.OnMenu
R.string.please_wait_for_data, Toast.LENGTH_LONG);
return false;
}
- boolean handled = FeedMenuHandler.onOptionsItemClicked(getContext(), item, feed);
-
- if (item.getItemId() == R.id.reconnect_local_folder) {
+ if (item.getItemId() == R.id.visit_website_item) {
+ IntentUtils.openInBrowser(getContext(), feed.getLink());
+ } else if (item.getItemId() == R.id.share_item) {
+ ShareUtils.shareFeedLink(getContext(), feed);
+ } else if (item.getItemId() == R.id.reconnect_local_folder) {
MaterialAlertDialogBuilder alert = new MaterialAlertDialogBuilder(getContext());
alert.setMessage(R.string.reconnect_local_folder_warning);
alert.setPositiveButton(android.R.string.ok, (dialog, which) -> {
@@ -304,23 +305,19 @@ public class FeedInfoFragment extends Fragment implements MaterialToolbar.OnMenu
});
alert.setNegativeButton(android.R.string.cancel, null);
alert.show();
- return true;
- }
-
- if (item.getItemId() == R.id.edit_feed_url_item) {
+ } else if (item.getItemId() == R.id.edit_feed_url_item) {
new EditUrlSettingsDialog(getActivity(), feed) {
@Override
protected void setUrl(String url) {
feed.setDownload_url(url);
- txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}");
- Iconify.addIcons(txtvUrl);
+ txtvUrl.setText(feed.getDownload_url());
+ txtvUrl.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_paperclip, 0);
}
}.show();
-
- return true;
+ } else {
+ return false;
}
-
- return handled;
+ return true;
}
private void addLocalFolderResult(final Uri uri) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
index 1c949218a..8020235b9 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
@@ -4,8 +4,6 @@ import android.content.Context;
import android.content.res.Configuration;
import android.graphics.LightingColorFilter;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
@@ -15,31 +13,48 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Toast;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
-import com.google.android.material.appbar.MaterialToolbar;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
+
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
+import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.snackbar.Snackbar;
import com.joanzapata.iconify.Iconify;
import com.leinardi.android.speeddial.SpeedDialView;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.EpisodeItemListAdapter;
import de.danoeh.antennapod.core.feed.FeedEvent;
import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.FeedItemPermutors;
import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.core.util.IntentUtils;
+import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.download.FeedUpdateManager;
import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil;
import de.danoeh.antennapod.databinding.FeedItemListFragmentBinding;
import de.danoeh.antennapod.databinding.MultiSelectSpeedDialBinding;
import de.danoeh.antennapod.dialog.DownloadLogDetailsDialog;
import de.danoeh.antennapod.dialog.FeedItemFilterDialog;
+import de.danoeh.antennapod.dialog.ItemSortDialog;
import de.danoeh.antennapod.dialog.RemoveFeedDialog;
import de.danoeh.antennapod.dialog.RenameItemDialog;
import de.danoeh.antennapod.event.EpisodeDownloadEvent;
@@ -54,11 +69,11 @@ import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
import de.danoeh.antennapod.fragment.actions.EpisodeMultiSelectActionHandler;
import de.danoeh.antennapod.fragment.swipeactions.SwipeActions;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
-import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
import de.danoeh.antennapod.model.download.DownloadResult;
import de.danoeh.antennapod.model.feed.Feed;
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.glide.FastBlurTransformation;
import de.danoeh.antennapod.view.ToolbarIconTintManager;
@@ -68,13 +83,6 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
-import org.apache.commons.lang3.Validate;
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-
-import java.util.Collections;
-import java.util.List;
/**
* Displays a list of FeedItems.
@@ -183,11 +191,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
EventBus.getDefault().register(this);
viewBinding.swipeRefresh.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance));
- viewBinding.swipeRefresh.setOnRefreshListener(() -> {
- FeedUpdateManager.runOnceOrAsk(requireContext(), feed);
- new Handler(Looper.getMainLooper()).postDelayed(() -> viewBinding.swipeRefresh.setRefreshing(false),
- getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms));
- });
+ viewBinding.swipeRefresh.setOnRefreshListener(() -> FeedUpdateManager.runOnceOrAsk(requireContext(), feed));
loadItems();
@@ -240,8 +244,13 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
return;
}
viewBinding.toolbar.getMenu().findItem(R.id.visit_website_item).setVisible(feed.getLink() != null);
-
- FeedMenuHandler.onPrepareOptionsMenu(viewBinding.toolbar.getMenu(), feed);
+ viewBinding.toolbar.getMenu().findItem(R.id.refresh_complete_item).setVisible(feed.isPaged());
+ if (StringUtils.isBlank(feed.getLink())) {
+ viewBinding.toolbar.getMenu().findItem(R.id.visit_website_item).setVisible(false);
+ }
+ if (feed.isLocalFeed()) {
+ viewBinding.toolbar.getMenu().findItem(R.id.share_item).setVisible(false);
+ }
}
@Override
@@ -260,26 +269,39 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
R.string.please_wait_for_data, Toast.LENGTH_LONG);
return true;
}
- boolean feedMenuHandled = FeedMenuHandler.onOptionsItemClicked(getActivity(), item, feed);
- if (feedMenuHandled) {
- return true;
- }
- final int itemId = item.getItemId();
- if (itemId == R.id.rename_item) {
+ if (item.getItemId() == R.id.visit_website_item) {
+ IntentUtils.openInBrowser(getContext(), feed.getLink());
+ } else if (item.getItemId() == R.id.share_item) {
+ ShareUtils.shareFeedLink(getContext(), feed);
+ } else if (item.getItemId() == R.id.refresh_item) {
+ FeedUpdateManager.runOnceOrAsk(getContext(), feed);
+ } else if (item.getItemId() == R.id.refresh_complete_item) {
+ new Thread(() -> {
+ feed.setNextPageLink(feed.getDownload_url());
+ feed.setPageNr(0);
+ try {
+ DBWriter.resetPagedFeedPage(feed).get();
+ FeedUpdateManager.runOnce(getContext(), feed);
+ } catch (ExecutionException | InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }).start();
+ } else if (item.getItemId() == R.id.sort_items) {
+ SingleFeedSortDialog.newInstance(feed).show(getChildFragmentManager(), "SortDialog");
+ } else if (item.getItemId() == R.id.rename_item) {
new RenameItemDialog(getActivity(), feed).show();
- return true;
- } else if (itemId == R.id.remove_feed) {
+ } else if (item.getItemId() == R.id.remove_feed) {
RemoveFeedDialog.show(getContext(), feed, () -> {
((MainActivity) getActivity()).loadFragment(UserPreferences.getDefaultPage(), null);
// Make sure fragment is hidden before actually starting to delete
getActivity().getSupportFragmentManager().executePendingTransactions();
});
- return true;
- } else if (itemId == R.id.action_search) {
+ } else if (item.getItemId() == R.id.action_search) {
((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(feed.getId(), feed.getTitle()));
- return true;
+ } else {
+ return false;
}
- return false;
+ return true;
}
@Override
@@ -407,8 +429,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
if (!event.isFeedUpdateRunning) {
nextPageLoader.getRoot().setVisibility(View.GONE);
}
- MenuItemUtils.updateRefreshMenuItem(viewBinding.toolbar.getMenu(),
- R.id.refresh_item, event.isFeedUpdateRunning);
+ viewBinding.swipeRefresh.setRefreshing(event.isFeedUpdateRunning);
}
private void refreshHeaderView() {
@@ -592,4 +613,45 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
MenuItemUtils.setOnClickListeners(menu, FeedItemlistFragment.this::onContextItemSelected);
}
}
+
+ public static class SingleFeedSortDialog extends ItemSortDialog {
+ private static final String ARG_FEED_ID = "feedId";
+ private static final String ARG_FEED_IS_LOCAL = "isLocal";
+ private static final String ARG_SORT_ORDER = "sortOrder";
+
+ private static SingleFeedSortDialog newInstance(Feed feed) {
+ Bundle bundle = new Bundle();
+ bundle.putLong(ARG_FEED_ID, feed.getId());
+ bundle.putBoolean(ARG_FEED_IS_LOCAL, feed.isLocalFeed());
+ if (feed.getSortOrder() == null) {
+ bundle.putString(ARG_SORT_ORDER, String.valueOf(SortOrder.DATE_NEW_OLD.code));
+ } else {
+ bundle.putString(ARG_SORT_ORDER, String.valueOf(feed.getSortOrder().code));
+ }
+ SingleFeedSortDialog dialog = new SingleFeedSortDialog();
+ dialog.setArguments(bundle);
+ return dialog;
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ sortOrder = SortOrder.fromCodeString(getArguments().getString(ARG_SORT_ORDER));
+ }
+
+ @Override
+ protected void onAddItem(int title, SortOrder ascending, SortOrder descending, boolean ascendingIsDefault) {
+ if (ascending == SortOrder.DATE_OLD_NEW || ascending == SortOrder.DURATION_SHORT_LONG
+ || ascending == SortOrder.EPISODE_TITLE_A_Z
+ || (getArguments().getBoolean(ARG_FEED_IS_LOCAL) && ascending == SortOrder.EPISODE_FILENAME_A_Z)) {
+ super.onAddItem(title, ascending, descending, ascendingIsDefault);
+ }
+ }
+
+ @Override
+ protected void onSelectionChanged() {
+ super.onSelectionChanged();
+ DBWriter.setFeedItemSortOrder(getArguments().getLong(ARG_FEED_ID), sortOrder);
+ }
+ }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/InboxFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/InboxFragment.java
index f8bcbb532..497409e70 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/InboxFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/InboxFragment.java
@@ -4,26 +4,25 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
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.CheckBox;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
-
+import androidx.annotation.Nullable;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
+import de.danoeh.antennapod.dialog.ItemSortDialog;
+import de.danoeh.antennapod.event.FeedListUpdateEvent;
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 org.greenrobot.eventbus.EventBus;
import java.util.List;
@@ -42,8 +41,6 @@ public class InboxFragment extends EpisodesListFragment {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View root = super.onCreateView(inflater, container, savedInstanceState);
toolbar.inflateMenu(R.menu.inbox);
- inflateSortMenu();
-
toolbar.setTitle(R.string.inbox_label);
prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
updateToolbar();
@@ -83,13 +80,9 @@ public class InboxFragment extends EpisodesListFragment {
showRemoveAllDialog();
}
return true;
- } else {
- SortOrder sortOrder = MenuItemToSortOrderConverter.convert(item);
- if (sortOrder != null) {
- UserPreferences.setInboxSortedOrder(sortOrder);
- loadItems();
- return true;
- }
+ } else if (item.getItemId() == R.id.inbox_sort) {
+ new InboxSortDialog().show(getChildFragmentManager(), "SortDialog");
+ return true;
}
return false;
}
@@ -118,20 +111,6 @@ public class InboxFragment extends EpisodesListFragment {
((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.removed_all_inbox_msg, Toast.LENGTH_SHORT);
}
- private void inflateSortMenu() {
- Menu menu = toolbar.getMenu();
- MenuItem downloadsItem = menu.findItem(R.id.inbox_sort);
- MenuInflater menuInflater = getActivity().getMenuInflater();
- menuInflater.inflate(R.menu.sort_menu, downloadsItem.getSubMenu());
-
- // Remove the sorting options that are not needed in this fragment
- toolbar.getMenu().findItem(R.id.sort_episode_title).setVisible(false);
- toolbar.getMenu().findItem(R.id.sort_feed_title).setVisible(false);
- toolbar.getMenu().findItem(R.id.sort_random).setVisible(false);
- toolbar.getMenu().findItem(R.id.sort_smart_shuffle).setVisible(false);
- toolbar.getMenu().findItem(R.id.keep_sorted).setVisible(false);
- }
-
private void showRemoveAllDialog() {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext());
builder.setTitle(R.string.remove_all_inbox_label);
@@ -149,4 +128,26 @@ public class InboxFragment extends EpisodesListFragment {
builder.setNegativeButton(R.string.cancel_label, null);
builder.show();
}
+
+ public static class InboxSortDialog extends ItemSortDialog {
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ sortOrder = UserPreferences.getInboxSortedOrder();
+ }
+
+ @Override
+ protected void onAddItem(int title, SortOrder ascending, SortOrder descending, boolean ascendingIsDefault) {
+ if (ascending == SortOrder.DATE_OLD_NEW || ascending == SortOrder.DURATION_SHORT_LONG) {
+ super.onAddItem(title, ascending, descending, ascendingIsDefault);
+ }
+ }
+
+ @Override
+ protected void onSelectionChanged() {
+ super.onSelectionChanged();
+ UserPreferences.setInboxSortedOrder(sortOrder);
+ EventBus.getDefault().post(new FeedListUpdateEvent(0));
+ }
+ }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/MenuItemToSortOrderConverter.java b/app/src/main/java/de/danoeh/antennapod/fragment/MenuItemToSortOrderConverter.java
deleted file mode 100644
index d4150fbdb..000000000
--- a/app/src/main/java/de/danoeh/antennapod/fragment/MenuItemToSortOrderConverter.java
+++ /dev/null
@@ -1,44 +0,0 @@
-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;
- } else if (itemId == R.id.sort_size_small_large) {
- return SortOrder.SIZE_SMALL_LARGE;
- } else if (itemId == R.id.sort_size_large_small) {
- return SortOrder.SIZE_LARGE_SMALL;
- }
-
- 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 eeca181cf..636c0245b 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java
@@ -382,7 +382,7 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
}
} else if (UserPreferences.getSubscriptionsFilter().isEnabled()
&& navAdapter.showSubscriptionList) {
- SubscriptionsFilterDialog.showDialog(requireContext());
+ new SubscriptionsFilterDialog().show(getChildFragmentManager(), "filter");
}
}
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 80933023e..003ee23db 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -4,29 +4,36 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
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;
import android.widget.CheckBox;
import android.widget.ProgressBar;
import android.widget.TextView;
+
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
import com.leinardi.android.speeddial.SpeedDialView;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.util.List;
+
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.EpisodeItemListAdapter;
@@ -39,6 +46,7 @@ import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.download.FeedUpdateManager;
+import de.danoeh.antennapod.dialog.ItemSortDialog;
import de.danoeh.antennapod.event.EpisodeDownloadEvent;
import de.danoeh.antennapod.event.FeedItemEvent;
import de.danoeh.antennapod.event.FeedUpdateRunningEvent;
@@ -61,12 +69,6 @@ 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.List;
-import java.util.Locale;
/**
* Shows all items in the queue.
@@ -81,6 +83,7 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
private QueueRecyclerAdapter recyclerAdapter;
private EmptyViewHandler emptyView;
private MaterialToolbar toolbar;
+ private SwipeRefreshLayout swipeRefreshLayout;
private boolean displayUpArrow;
private List<FeedItem> queue;
@@ -159,6 +162,8 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
case MOVED:
return;
}
+ recyclerAdapter.updateDragDropEnabled();
+ refreshToolbarState();
recyclerView.saveScrollPosition(QueueFragment.TAG);
refreshInfoBar();
}
@@ -258,13 +263,11 @@ 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.sort_random).setVisible(!keepSorted);
- toolbar.getMenu().findItem(R.id.keep_sorted).setChecked(keepSorted);
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEventMainThread(FeedUpdateRunningEvent event) {
- MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(), R.id.refresh_item, event.isFeedUpdateRunning);
+ swipeRefreshLayout.setRefreshing(event.isFeedUpdateRunning);
}
@Override
@@ -273,6 +276,9 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
if (itemId == R.id.queue_lock) {
toggleQueueLock();
return true;
+ } else if (itemId == R.id.queue_sort) {
+ new QueueSortDialog().show(getChildFragmentManager().beginTransaction(), "SortDialog");
+ return true;
} else if (itemId == R.id.refresh_item) {
FeedUpdateManager.runOnceOrAsk(requireContext());
return true;
@@ -291,28 +297,9 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
};
conDialog.createNewDialog().show();
return true;
- } else if (itemId == R.id.keep_sorted) {
- boolean keepSortedOld = UserPreferences.isQueueKeepSorted();
- boolean keepSortedNew = !keepSortedOld;
- UserPreferences.setQueueKeepSorted(keepSortedNew);
- if (keepSortedNew) {
- SortOrder sortOrder = UserPreferences.getQueueKeepSortedOrder();
- DBWriter.reorderQueue(sortOrder, true);
- }
- if (recyclerAdapter != null) {
- recyclerAdapter.updateDragDropEnabled();
- }
- refreshToolbarState();
- return true;
} 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;
}
@@ -359,16 +346,6 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
}
}
- /**
- * This method is called if the user clicks on a sort order menu item.
- *
- * @param sortOrder New sort order.
- */
- private void setSortOrder(SortOrder sortOrder) {
- UserPreferences.setQueueKeepSortedOrder(sortOrder);
- DBWriter.reorderQueue(sortOrder, true);
- }
-
@Override
public boolean onContextItemSelected(MenuItem item) {
Log.d(TAG, "onContextItemSelected() called with: " + "item = [" + item + "]");
@@ -422,10 +399,6 @@ 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);
@@ -454,13 +427,9 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
recyclerAdapter.setOnSelectModeListener(this);
recyclerView.setAdapter(recyclerAdapter);
- SwipeRefreshLayout swipeRefreshLayout = root.findViewById(R.id.swipeRefresh);
+ swipeRefreshLayout = root.findViewById(R.id.swipeRefresh);
swipeRefreshLayout.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance));
- swipeRefreshLayout.setOnRefreshListener(() -> {
- FeedUpdateManager.runOnceOrAsk(requireContext());
- new Handler(Looper.getMainLooper()).postDelayed(() -> swipeRefreshLayout.setRefreshing(false),
- getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms));
- });
+ swipeRefreshLayout.setOnRefreshListener(() -> FeedUpdateManager.runOnceOrAsk(requireContext()));
emptyView = new EmptyViewHandler(getContext());
emptyView.attachToRecyclerView(recyclerView);
@@ -507,9 +476,8 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
}
private void refreshInfoBar() {
- String info = String.format(Locale.getDefault(), "%d%s",
- queue.size(), getString(R.string.episodes_suffix));
- if (queue.size() > 0) {
+ String info = getResources().getQuantityString(R.plurals.num_episodes, queue.size(), queue.size());
+ if (!queue.isEmpty()) {
long timeLeft = 0;
for (FeedItem item : queue) {
float playbackSpeed = 1;
@@ -567,6 +535,42 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
swipeActions.attachTo(recyclerView);
}
+ public static class QueueSortDialog extends ItemSortDialog {
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater,
+ @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ if (UserPreferences.isQueueKeepSorted()) {
+ sortOrder = UserPreferences.getQueueKeepSortedOrder();
+ }
+ final View view = super.onCreateView(inflater, container, savedInstanceState);
+ viewBinding.keepSortedCheckbox.setVisibility(View.VISIBLE);
+ viewBinding.keepSortedCheckbox.setChecked(UserPreferences.isQueueKeepSorted());
+ // Disable until something gets selected
+ viewBinding.keepSortedCheckbox.setEnabled(UserPreferences.isQueueKeepSorted());
+ return view;
+ }
+
+ @Override
+ protected void onAddItem(int title, SortOrder ascending, SortOrder descending, boolean ascendingIsDefault) {
+ if (ascending != SortOrder.EPISODE_FILENAME_A_Z && ascending != SortOrder.SIZE_SMALL_LARGE) {
+ super.onAddItem(title, ascending, descending, ascendingIsDefault);
+ }
+ }
+
+ @Override
+ protected void onSelectionChanged() {
+ super.onSelectionChanged();
+ viewBinding.keepSortedCheckbox.setEnabled(sortOrder != SortOrder.RANDOM);
+ if (sortOrder == SortOrder.RANDOM) {
+ viewBinding.keepSortedCheckbox.setChecked(false);
+ }
+ UserPreferences.setQueueKeepSorted(viewBinding.keepSortedCheckbox.isChecked());
+ UserPreferences.setQueueKeepSortedOrder(sortOrder);
+ DBWriter.reorderQueue(sortOrder, true);
+ }
+ }
+
private class QueueSwipeActions extends SwipeActions {
// Position tracking whilst dragging
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 93ed4c2c9..e86cd58b9 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
@@ -3,8 +3,6 @@ package de.danoeh.antennapod.fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
@@ -81,6 +79,7 @@ public class SubscriptionFragment extends Fragment
private EmptyViewHandler emptyView;
private LinearLayout feedsFilteredMsg;
private MaterialToolbar toolbar;
+ private SwipeRefreshLayout swipeRefreshLayout;
private ProgressBar progressBar;
private String displayedFolder = null;
private boolean displayUpArrow;
@@ -166,15 +165,12 @@ public class SubscriptionFragment extends Fragment
});
feedsFilteredMsg = root.findViewById(R.id.feeds_filtered_message);
- feedsFilteredMsg.setOnClickListener((l) -> SubscriptionsFilterDialog.showDialog(requireContext()));
+ feedsFilteredMsg.setOnClickListener((l) ->
+ new SubscriptionsFilterDialog().show(getChildFragmentManager(), "filter"));
- SwipeRefreshLayout swipeRefreshLayout = root.findViewById(R.id.swipeRefresh);
+ swipeRefreshLayout = root.findViewById(R.id.swipeRefresh);
swipeRefreshLayout.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance));
- swipeRefreshLayout.setOnRefreshListener(() -> {
- FeedUpdateManager.runOnceOrAsk(requireContext());
- new Handler(Looper.getMainLooper()).postDelayed(() -> swipeRefreshLayout.setRefreshing(false),
- getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms));
- });
+ swipeRefreshLayout.setOnRefreshListener(() -> FeedUpdateManager.runOnceOrAsk(requireContext()));
speedDialView = root.findViewById(R.id.fabSD);
speedDialView.setOverlayLayout(root.findViewById(R.id.fabSDOverlay));
@@ -211,7 +207,7 @@ public class SubscriptionFragment extends Fragment
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEventMainThread(FeedUpdateRunningEvent event) {
- MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(), R.id.refresh_item, event.isFeedUpdateRunning);
+ swipeRefreshLayout.setRefreshing(event.isFeedUpdateRunning);
}
@Override
@@ -221,7 +217,7 @@ public class SubscriptionFragment extends Fragment
FeedUpdateManager.runOnceOrAsk(requireContext());
return true;
} else if (itemId == R.id.subscriptions_filter) {
- SubscriptionsFilterDialog.showDialog(requireContext());
+ new SubscriptionsFilterDialog().show(getChildFragmentManager(), "filter");
return true;
} else if (itemId == R.id.subscriptions_sort) {
FeedSortDialog.showDialog(requireContext());
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 66f592af2..0f3320e98 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
@@ -1,8 +1,10 @@
package de.danoeh.antennapod.fragment.preferences;
import android.content.Context;
+import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
+import android.widget.Button;
import android.widget.ListView;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
@@ -64,14 +66,14 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat {
return true;
});
- findPreference(UserPreferences.PREF_COMPACT_NOTIFICATION_BUTTONS)
+ findPreference(UserPreferences.PREF_FULL_NOTIFICATION_BUTTONS)
.setOnPreferenceClickListener(preference -> {
- showNotificationButtonsDialog();
+ showFullNotificationButtonsDialog();
return true;
});
findPreference(UserPreferences.PREF_FILTER_FEED)
.setOnPreferenceClickListener((preference -> {
- SubscriptionsFilterDialog.showDialog(requireContext());
+ new SubscriptionsFilterDialog().show(getChildFragmentManager(), "filter");
return true;
}));
@@ -91,48 +93,85 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat {
}
}
- private void showNotificationButtonsDialog() {
+
+ private void showFullNotificationButtonsDialog() {
final Context context = getActivity();
- final List<Integer> preferredButtons = UserPreferences.getCompactNotificationButtons();
+
+ final List<Integer> preferredButtons = UserPreferences.getFullNotificationButtons();
final String[] allButtonNames = context.getResources().getStringArray(
- R.array.compact_notification_buttons_options);
+ R.array.full_notification_buttons_options);
+ final int[] buttonIDs = {2, 3, 4};
+ final int exactItems = 2;
+ final DialogInterface.OnClickListener completeListener = (dialog, which) ->
+ UserPreferences.setFullNotificationButtons(preferredButtons);
+ final String title = context.getResources().getString(
+ R.string.pref_full_notification_buttons_title);
+
+ showNotificationButtonsDialog(preferredButtons, allButtonNames, buttonIDs, title,
+ exactItems, completeListener
+ );
+ }
+
+ private void showNotificationButtonsDialog(List<Integer> preferredButtons,
+ String[] allButtonNames, int[] buttonIds, String title,
+ int exactItems, DialogInterface.OnClickListener completeListener) {
boolean[] checked = new boolean[allButtonNames.length]; // booleans default to false in java
+ final Context context = getActivity();
+
+ // Clear buttons that are not part of the setting anymore
+ for (int i = preferredButtons.size() - 1; i >= 0; i--) {
+ boolean isValid = false;
+ for (int j = 0; j < checked.length; j++) {
+ if (buttonIds[j] == preferredButtons.get(i)) {
+ isValid = true;
+ }
+ }
+
+ if (!isValid) {
+ preferredButtons.remove(i);
+ }
+ }
+
for(int i=0; i < checked.length; i++) {
- if(preferredButtons.contains(i)) {
+ if (preferredButtons.contains(buttonIds[i])) {
checked[i] = true;
}
}
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context);
- builder.setTitle(String.format(context.getResources().getString(
- R.string.pref_compact_notification_buttons_dialog_title), 2));
+ builder.setTitle(title);
builder.setMultiChoiceItems(allButtonNames, checked, (dialog, which, isChecked) -> {
checked[which] = isChecked;
if (isChecked) {
- if (preferredButtons.size() < 2) {
- preferredButtons.add(which);
- } else {
- // Only allow a maximum of two selections. This is because the notification
- // on the lock screen can only display 3 buttons, and the play/pause button
- // is always included.
- checked[which] = false;
- ListView selectionView = ((AlertDialog) dialog).getListView();
- selectionView.setItemChecked(which, false);
- Snackbar.make(
- selectionView,
- String.format(context.getResources().getString(
- R.string.pref_compact_notification_buttons_dialog_error), 2),
- Snackbar.LENGTH_SHORT).show();
- }
+ preferredButtons.add(buttonIds[which]);
} else {
- preferredButtons.remove((Integer) which);
+ preferredButtons.remove((Integer) buttonIds[which]);
}
});
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) ->
- UserPreferences.setCompactNotificationButtons(preferredButtons));
+ builder.setPositiveButton(R.string.confirm_label, null);
builder.setNegativeButton(R.string.cancel_label, null);
- builder.create().show();
+ final AlertDialog dialog = builder.create();
+
+ dialog.show();
+
+ Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
+
+ positiveButton.setOnClickListener(v -> {
+ if (preferredButtons.size() != exactItems) {
+ ListView selectionView = dialog.getListView();
+ Snackbar.make(
+ selectionView,
+ String.format(context.getResources().getString(
+ R.string.pref_compact_notification_buttons_dialog_error_exact), exactItems),
+ Snackbar.LENGTH_SHORT).show();
+
+ } else {
+ completeListener.onClick(dialog, AlertDialog.BUTTON_POSITIVE);
+ dialog.cancel();
+ }
+ }
+ );
}
}
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 7a9eb1bb5..eac1e9304 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
@@ -1,103 +1,32 @@
package de.danoeh.antennapod.menuhandler;
+import android.annotation.SuppressLint;
import android.content.Context;
+import android.content.DialogInterface;
import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
import androidx.annotation.NonNull;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.util.IntentUtils;
-import de.danoeh.antennapod.core.util.ShareUtils;
-import de.danoeh.antennapod.core.util.download.FeedUpdateManager;
-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.R;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.dialog.RemoveFeedDialog;
import de.danoeh.antennapod.dialog.RenameItemDialog;
import de.danoeh.antennapod.dialog.TagSettingsDialog;
+import de.danoeh.antennapod.model.feed.Feed;
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.ExecutionException;
import java.util.concurrent.Future;
/**
* Handles interactions with the FeedItemMenu.
*/
-public class FeedMenuHandler {
-
- private FeedMenuHandler(){ }
-
+public abstract class FeedMenuHandler {
private static final String TAG = "FeedMenuHandler";
- public static boolean onPrepareOptionsMenu(Menu menu, Feed selectedFeed) {
- if (selectedFeed == null) {
- return true;
- }
-
- Log.d(TAG, "Preparing options menu");
-
- menu.findItem(R.id.refresh_complete_item).setVisible(selectedFeed.isPaged());
- if (StringUtils.isBlank(selectedFeed.getLink())) {
- menu.findItem(R.id.visit_website_item).setVisible(false);
- }
- if (selectedFeed.isLocalFeed()) {
- // hide complete submenu "Share..." as both sub menu items are not visible
- menu.findItem(R.id.share_item).setVisible(false);
- }
-
- return true;
- }
-
- /**
- * NOTE: This method does not handle clicks on the 'remove feed' - item.
- */
- public static boolean onOptionsItemClicked(final Context context, final MenuItem item, final Feed selectedFeed) {
- final int itemId = item.getItemId();
- if (itemId == R.id.refresh_item) {
- FeedUpdateManager.runOnceOrAsk(context, selectedFeed);
- } else if (itemId == R.id.refresh_complete_item) {
- new Thread(() -> {
- selectedFeed.setNextPageLink(selectedFeed.getDownload_url());
- selectedFeed.setPageNr(0);
- try {
- DBWriter.resetPagedFeedPage(selectedFeed).get();
- FeedUpdateManager.runOnce(context, selectedFeed);
- } catch (ExecutionException | InterruptedException e) {
- throw new RuntimeException(e);
- }
- }).start();
- } else if (itemId == R.id.sort_items) {
- showSortDialog(context, selectedFeed);
- } else if (itemId == R.id.visit_website_item) {
- IntentUtils.openInBrowser(context, selectedFeed.getLink());
- } else if (itemId == R.id.share_item) {
- ShareUtils.shareFeedLink(context, selectedFeed);
- } else {
- return false;
- }
- return true;
- }
-
- private static void showSortDialog(Context context, Feed selectedFeed) {
- IntraFeedSortDialog sortDialog = new IntraFeedSortDialog(context, selectedFeed.getSortOrder(), selectedFeed.isLocalFeed()) {
- @Override
- protected void updateSort(@NonNull SortOrder sortOrder) {
- selectedFeed.setSortOrder(sortOrder);
- DBWriter.setFeedItemSortOrder(selectedFeed.getId(), sortOrder);
- }
- };
- sortDialog.openDialog();
- }
-
public static boolean onMenuItemClicked(@NonNull Fragment fragment, int menuItemId,
@NonNull Feed selectedFeed, Runnable callback) {
@NonNull Context context = fragment.requireContext();
@@ -131,5 +60,4 @@ public class FeedMenuHandler {
}
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 cc298b38d..3a3063599 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java
@@ -6,12 +6,15 @@ import android.view.KeyEvent;
import androidx.core.app.NotificationManagerCompat;
import androidx.preference.PreferenceManager;
+import org.apache.commons.lang3.StringUtils;
+
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
import de.danoeh.antennapod.error.CrashReportWriter;
+import de.danoeh.antennapod.fragment.AllEpisodesFragment;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.storage.preferences.UserPreferences.EnqueueLocation;
import de.danoeh.antennapod.fragment.QueueFragment;
@@ -149,5 +152,19 @@ public class PreferenceUpgrader {
if (oldVersion < 3020000) {
NotificationManagerCompat.from(context).deleteNotificationChannel("auto_download");
}
+
+ if (oldVersion < 3030000) {
+ SharedPreferences allEpisodesPreferences =
+ context.getSharedPreferences(AllEpisodesFragment.PREF_NAME, Context.MODE_PRIVATE);
+ String oldEpisodeSort = allEpisodesPreferences.getString(UserPreferences.PREF_SORT_ALL_EPISODES, "");
+ if (!StringUtils.isAllEmpty(oldEpisodeSort)) {
+ prefs.edit().putString(UserPreferences.PREF_SORT_ALL_EPISODES, oldEpisodeSort).apply();
+ }
+
+ String oldEpisodeFilter = allEpisodesPreferences.getString("filter", "");
+ if (!StringUtils.isAllEmpty(oldEpisodeFilter)) {
+ prefs.edit().putString(UserPreferences.PREF_FILTER_ALL_EPISODES, oldEpisodeFilter).apply();
+ }
+ }
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/home/HomeFragment.java b/app/src/main/java/de/danoeh/antennapod/ui/home/HomeFragment.java
index fc925aa03..6f43a8ff4 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/home/HomeFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/home/HomeFragment.java
@@ -6,8 +6,6 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@@ -21,7 +19,6 @@ import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentContainerView;
-import de.danoeh.antennapod.ui.home.sections.EchoSection;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@@ -33,7 +30,6 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.util.download.FeedUpdateManager;
import de.danoeh.antennapod.databinding.HomeFragmentBinding;
@@ -41,8 +37,10 @@ import de.danoeh.antennapod.event.FeedListUpdateEvent;
import de.danoeh.antennapod.event.FeedUpdateRunningEvent;
import de.danoeh.antennapod.fragment.SearchFragment;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
+import de.danoeh.antennapod.ui.echo.EchoActivity;
import de.danoeh.antennapod.ui.home.sections.AllowNotificationsSection;
import de.danoeh.antennapod.ui.home.sections.DownloadsSection;
+import de.danoeh.antennapod.ui.home.sections.EchoSection;
import de.danoeh.antennapod.ui.home.sections.EpisodesSurpriseSection;
import de.danoeh.antennapod.ui.home.sections.InboxSection;
import de.danoeh.antennapod.ui.home.sections.QueueSection;
@@ -85,11 +83,7 @@ public class HomeFragment extends Fragment implements Toolbar.OnMenuItemClickLis
updateWelcomeScreenVisibility();
viewBinding.swipeRefresh.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance));
- viewBinding.swipeRefresh.setOnRefreshListener(() -> {
- FeedUpdateManager.runOnceOrAsk(requireContext());
- new Handler(Looper.getMainLooper()).postDelayed(() -> viewBinding.swipeRefresh.setRefreshing(false),
- getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms));
- });
+ viewBinding.swipeRefresh.setOnRefreshListener(() -> FeedUpdateManager.runOnceOrAsk(requireContext()));
return viewBinding.getRoot();
}
@@ -104,10 +98,10 @@ public class HomeFragment extends Fragment implements Toolbar.OnMenuItemClickLis
addSection(new AllowNotificationsSection());
}
}
- if (Calendar.getInstance().get(Calendar.MONTH) == Calendar.DECEMBER
- && Calendar.getInstance().get(Calendar.YEAR) == 2023
+ if (Calendar.getInstance().get(Calendar.YEAR) == EchoActivity.RELEASE_YEAR
+ && Calendar.getInstance().get(Calendar.MONTH) == Calendar.DECEMBER
&& Calendar.getInstance().get(Calendar.DAY_OF_MONTH) >= 10
- && prefs.getInt(PREF_HIDE_ECHO, 0) != 2023) {
+ && prefs.getInt(PREF_HIDE_ECHO, 0) != EchoActivity.RELEASE_YEAR) {
addSection(new EchoSection());
}
@@ -153,8 +147,7 @@ public class HomeFragment extends Fragment implements Toolbar.OnMenuItemClickLis
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEventMainThread(FeedUpdateRunningEvent event) {
- MenuItemUtils.updateRefreshMenuItem(viewBinding.toolbar.getMenu(),
- R.id.refresh_item, event.isFeedUpdateRunning);
+ viewBinding.swipeRefresh.setRefreshing(event.isFeedUpdateRunning);
}
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/home/sections/EchoSection.java b/app/src/main/java/de/danoeh/antennapod/ui/home/sections/EchoSection.java
index 7261c6be4..05b716abb 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/home/sections/EchoSection.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/home/sections/EchoSection.java
@@ -32,13 +32,9 @@ public class EchoSection extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
viewBinding = HomeSectionEchoBinding.inflate(inflater);
- viewBinding.titleLabel.setText(getString(R.string.antennapod_echo_year, 2023));
+ viewBinding.titleLabel.setText(getString(R.string.antennapod_echo_year, EchoActivity.RELEASE_YEAR));
viewBinding.echoButton.setOnClickListener(v -> startActivity(new Intent(getContext(), EchoActivity.class)));
- viewBinding.closeButton.setOnClickListener(v -> {
- getContext().getSharedPreferences(HomeFragment.PREF_NAME, Context.MODE_PRIVATE)
- .edit().putInt(HomeFragment.PREF_HIDE_ECHO, 2023).apply();
- ((MainActivity) getActivity()).loadFragment(HomeFragment.TAG, null);
- });
+ viewBinding.closeButton.setOnClickListener(v -> hideThisYear());
updateVisibility();
return viewBinding.getRoot();
}
@@ -51,7 +47,7 @@ public class EchoSection extends Fragment {
date.set(Calendar.MILLISECOND, 0);
date.set(Calendar.DAY_OF_MONTH, 1);
date.set(Calendar.MONTH, 0);
- date.set(Calendar.YEAR, 2023);
+ date.set(Calendar.YEAR, EchoActivity.RELEASE_YEAR);
return date.getTimeInMillis();
}
@@ -70,8 +66,18 @@ public class EchoSection extends Fragment {
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(totalTime -> viewBinding.getRoot()
- .setVisibility((totalTime >= 3600 * 10) ? View.VISIBLE : View.GONE),
- Throwable::printStackTrace);
+ .subscribe(totalTime -> {
+ boolean shouldShow = (totalTime >= 3600 * 10);
+ viewBinding.getRoot().setVisibility(shouldShow ? View.VISIBLE : View.GONE);
+ if (!shouldShow) {
+ hideThisYear();
+ }
+ }, Throwable::printStackTrace);
+ }
+
+ void hideThisYear() {
+ getContext().getSharedPreferences(HomeFragment.PREF_NAME, Context.MODE_PRIVATE)
+ .edit().putInt(HomeFragment.PREF_HIDE_ECHO, EchoActivity.RELEASE_YEAR).apply();
+ ((MainActivity) getActivity()).loadFragment(HomeFragment.TAG, null);
}
}
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 b4f61a19a..01d4a10f0 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
@@ -100,15 +100,13 @@ public class EpisodeItemViewHolder extends RecyclerView.ViewHolder {
this.item = item;
placeholder.setText(item.getFeed().getTitle());
title.setText(item.getTitle());
- leftPadding.setContentDescription(item.getTitle());
- pubDate.setText(DateFormatter.formatAbbrev(activity, item.getPubDate()));
- pubDate.setContentDescription(DateFormatter.formatForAccessibility(item.getPubDate()));
if (item.isPlayed()) {
- cover.setContentDescription(activity.getString(R.string.is_played));
- cover.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ leftPadding.setContentDescription(item.getTitle() + ". " + activity.getString(R.string.is_played));
} else {
- cover.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ leftPadding.setContentDescription(item.getTitle());
}
+ pubDate.setText(DateFormatter.formatAbbrev(activity, item.getPubDate()));
+ pubDate.setContentDescription(DateFormatter.formatForAccessibility(item.getPubDate()));
isInbox.setVisibility(item.isNew() ? View.VISIBLE : View.GONE);
isFavorite.setVisibility(item.isTagged(FeedItem.TAG_FAVORITE) ? View.VISIBLE : View.GONE);
isInQueue.setVisibility(item.isTagged(FeedItem.TAG_QUEUE) ? View.VISIBLE : View.GONE);