Update filter dialog to Fragment

This commit is contained in:
ByteHamster 2022-04-22 20:53:29 +02:00
parent 8775031b20
commit 0b431a3311
9 changed files with 182 additions and 138 deletions

View File

@ -0,0 +1,31 @@
package de.danoeh.antennapod.dialog;
import android.os.Bundle;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
import org.greenrobot.eventbus.EventBus;
import java.util.Set;
public class AllEpisodesFilterDialog extends ItemFilterDialog {
public static AllEpisodesFilterDialog newInstance(FeedItemFilter filter) {
AllEpisodesFilterDialog dialog = new AllEpisodesFilterDialog();
Bundle arguments = new Bundle();
arguments.putSerializable(ARGUMENT_FILTER, filter);
dialog.setArguments(arguments);
return dialog;
}
@Override
void onFilterChanged(Set<String> newFilterValues) {
EventBus.getDefault().post(new AllEpisodesFilterChangedEvent(newFilterValues));
}
public static class AllEpisodesFilterChangedEvent {
public final Set<String> filterValues;
public AllEpisodesFilterChangedEvent(Set<String> filterValues) {
this.filterValues = filterValues;
}
}
}

View File

@ -0,0 +1,26 @@
package de.danoeh.antennapod.dialog;
import android.os.Bundle;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.model.feed.Feed;
import java.util.Set;
public class FeedItemFilterDialog extends ItemFilterDialog {
private static final String ARGUMENT_FEED_ID = "feedId";
public static FeedItemFilterDialog newInstance(Feed feed) {
FeedItemFilterDialog dialog = new FeedItemFilterDialog();
Bundle arguments = new Bundle();
arguments.putSerializable(ARGUMENT_FILTER, feed.getItemFilter());
arguments.putLong(ARGUMENT_FEED_ID, feed.getId());
dialog.setArguments(arguments);
return dialog;
}
@Override
void onFilterChanged(Set<String> newFilterValues) {
long feedId = getArguments().getLong(ARGUMENT_FEED_ID);
DBWriter.setFeedItemsFilter(feedId, newFilterValues);
}
}

View File

@ -1,83 +0,0 @@
package de.danoeh.antennapod.dialog;
import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import androidx.appcompat.app.AlertDialog;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
import de.danoeh.antennapod.core.feed.FeedItemFilterGroup;
import de.danoeh.antennapod.ui.common.RecursiveRadioGroup;
public abstract class FilterDialog {
protected FeedItemFilter filter;
protected Context context;
public FilterDialog(Context context, FeedItemFilter feedItemFilter) {
this.context = context;
this.filter = feedItemFilter;
}
public void openDialog() {
final Set<String> filterValues = new HashSet<>(Arrays.asList(filter.getValues()));
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.filter);
LayoutInflater inflater = LayoutInflater.from(this.context);
View layout = inflater.inflate(R.layout.filter_dialog, null, false);
LinearLayout rows = layout.findViewById(R.id.filter_rows);
builder.setView(layout);
for (FeedItemFilterGroup item : FeedItemFilterGroup.values()) {
RecursiveRadioGroup row = (RecursiveRadioGroup) inflater.inflate(R.layout.filter_dialog_row, null, false);
RadioButton filter1 = row.findViewById(R.id.filter_dialog_radioButton1);
RadioButton filter2 = row.findViewById(R.id.filter_dialog_radioButton2);
filter1.setText(item.values[0].displayName);
filter1.setTag(item.values[0].filterId);
filter2.setText(item.values[1].displayName);
filter2.setTag(item.values[1].filterId);
rows.addView(row);
}
for (String filterId : filterValues) {
if (!TextUtils.isEmpty(filterId)) {
RadioButton button = layout.findViewWithTag(filterId);
if (button != null) {
button.setChecked(true);
}
}
}
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
filterValues.clear();
for (int i = 0; i < rows.getChildCount(); i++) {
if (!(rows.getChildAt(i) instanceof RecursiveRadioGroup)) {
continue;
}
RecursiveRadioGroup group = (RecursiveRadioGroup) rows.getChildAt(i);
if (group.getCheckedButton() != null) {
String tag = (String) group.getCheckedButton().getTag();
if (tag != null) { // Clear buttons use no tag
filterValues.add((String) group.getCheckedButton().getTag());
}
}
}
updateFilter(filterValues);
});
builder.setNegativeButton(R.string.cancel_label, null);
builder.create().show();
}
protected abstract void updateFilter(Set<String> filterValues);
}

View File

@ -0,0 +1,75 @@
package de.danoeh.antennapod.dialog;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItemFilterGroup;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
import de.danoeh.antennapod.ui.common.RecursiveRadioGroup;
import java.util.HashSet;
import java.util.Set;
public abstract class ItemFilterDialog extends BottomSheetDialogFragment {
protected static final String ARGUMENT_FILTER = "filter";
private LinearLayout rows;
@Nullable
@Override
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);
FeedItemFilter filter = (FeedItemFilter) getArguments().getSerializable(ARGUMENT_FILTER);
for (FeedItemFilterGroup item : FeedItemFilterGroup.values()) {
RecursiveRadioGroup row = (RecursiveRadioGroup) inflater.inflate(R.layout.filter_dialog_row, null, false);
row.setOnCheckedChangeListener((group, checkedId) -> onFilterChanged(getNewFilterValues()));
RadioButton filter1 = row.findViewById(R.id.filter_dialog_radioButton1);
RadioButton filter2 = row.findViewById(R.id.filter_dialog_radioButton2);
filter1.setText(item.values[0].displayName);
filter1.setTag(item.values[0].filterId);
filter2.setText(item.values[1].displayName);
filter2.setTag(item.values[1].filterId);
rows.addView(row);
}
for (String filterId : filter.getValues()) {
if (!TextUtils.isEmpty(filterId)) {
RadioButton button = layout.findViewWithTag(filterId);
if (button != null) {
button.setChecked(true);
}
}
}
return layout;
}
protected Set<String> getNewFilterValues() {
final Set<String> newFilterValues = new HashSet<>();
for (int i = 0; i < rows.getChildCount(); i++) {
if (!(rows.getChildAt(i) instanceof RecursiveRadioGroup)) {
continue;
}
RecursiveRadioGroup group = (RecursiveRadioGroup) rows.getChildAt(i);
if (group.getCheckedButton() != null) {
String tag = (String) group.getCheckedButton().getTag();
if (tag != null) { // Clear buttons use no tag
newFilterValues.add((String) group.getCheckedButton().getTag());
}
}
}
return newFilterValues;
}
abstract void onFilterChanged(Set<String> newFilterValues);
}

View File

@ -10,14 +10,14 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.joanzapata.iconify.Iconify;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.dialog.AllEpisodesFilterDialog;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.dialog.FilterDialog;
import org.apache.commons.lang3.StringUtils;
import org.greenrobot.eventbus.Subscribe;
import java.util.List;
import java.util.Set;
/**
* Like 'EpisodesFragment' except that it only shows new episodes and
@ -43,15 +43,22 @@ public class AllEpisodesFragment extends EpisodesListFragment {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!super.onOptionsItemSelected(item)) {
if (item.getItemId() == R.id.filter_items) {
showFilterDialog();
return true;
}
return false;
} else {
if (super.onOptionsItemSelected(item)) {
return true;
}
if (item.getItemId() == R.id.filter_items) {
AllEpisodesFilterDialog.newInstance(feedItemFilter).show(getChildFragmentManager(), null);
return true;
}
return false;
}
@Subscribe
public void onFilterChanged(AllEpisodesFilterDialog.AllEpisodesFilterChangedEvent event) {
feedItemFilter = new FeedItemFilter(event.filterValues.toArray(new String[0]));
SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
prefs.edit().putString(PREF_FILTER, StringUtils.join(event.filterValues, ",")).apply();
loadItems();
}
@Override
@ -75,20 +82,6 @@ public class AllEpisodesFragment extends EpisodesListFragment {
}
}
private void showFilterDialog() {
FilterDialog filterDialog = new FilterDialog(getContext(), feedItemFilter) {
@Override
protected void updateFilter(Set<String> filterValues) {
feedItemFilter = new FeedItemFilter(filterValues.toArray(new String[0]));
SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
prefs.edit().putString(PREF_FILTER, StringUtils.join(filterValues, ",")).apply();
loadItems();
}
};
filterDialog.openDialog();
}
@Override
protected boolean shouldUpdatedItemRemainInList(FeedItem item) {
SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);

View File

@ -39,14 +39,13 @@ import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.FeedItemPermutors;
import de.danoeh.antennapod.core.util.FeedItemUtil;
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.FilterDialog;
import de.danoeh.antennapod.dialog.FeedItemFilterDialog;
import de.danoeh.antennapod.dialog.RemoveFeedDialog;
import de.danoeh.antennapod.dialog.RenameItemDialog;
import de.danoeh.antennapod.event.FavoritesEvent;
@ -77,7 +76,6 @@ import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
import java.util.Set;
/**
* Displays a list of FeedItems.
@ -469,17 +467,8 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
viewBinding.header.txtvInformation.setText("{md-info-outline} "
+ this.getString(R.string.filtered_label));
Iconify.addIcons(viewBinding.header.txtvInformation);
viewBinding.header.txtvInformation.setOnClickListener((l) -> {
FilterDialog filterDialog = new FilterDialog(requireContext(), feed.getItemFilter()) {
@Override
protected void updateFilter(Set<String> filterValues) {
feed.setItemFilter(filterValues.toArray(new String[0]));
DBWriter.setFeedItemsFilter(feed.getId(), filterValues);
}
};
filterDialog.openDialog();
});
viewBinding.header.txtvInformation.setOnClickListener(l ->
FeedItemFilterDialog.newInstance(feed).show(getChildFragmentManager(), null));
viewBinding.header.txtvInformation.setVisibility(View.VISIBLE);
} else {
viewBinding.header.txtvInformation.setVisibility(View.GONE);
@ -504,14 +493,8 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
((MainActivity) getActivity()).loadChildFragment(fragment, TransitionEffect.SLIDE);
}
});
viewBinding.header.butFilter.setOnClickListener(
v -> new FilterDialog(getContext(), feed.getItemFilter()) {
@Override
protected void updateFilter(Set<String> filterValues) {
feed.setItemFilter(filterValues.toArray(new String[0]));
DBWriter.setFeedItemsFilter(feed.getId(), filterValues);
}
}.openDialog());
viewBinding.header.butFilter.setOnClickListener(v ->
FeedItemFilterDialog.newInstance(feed).show(getChildFragmentManager(), null));
viewBinding.header.txtvFailure.setOnClickListener(v -> showErrorDetails());
headerCreated = true;
}

View File

@ -12,6 +12,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:clipChildren="true"
android:layout_gravity="center_vertical"
app:cardCornerRadius="32dp"
app:cardElevation="0dp">
@ -28,34 +29,38 @@
android:layout_marginRight="2dp"
android:layout_weight="1"
android:background="?attr/filter_dialog_button_background"
style="@style/NoButtonRadio"
android:minHeight="40dp"
android:foreground="?android:attr/selectableItemBackground"
android:checked="false"
android:gravity="center"
android:textColor="@color/filter_dialog_button_text" />
android:textColor="@color/filter_dialog_button_text"
style="@style/NoButtonRadio" />
<RadioButton
android:id="@+id/filter_dialog_radioButton2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:minHeight="40dp"
android:layout_weight="1"
android:background="?attr/filter_dialog_button_background"
style="@style/NoButtonRadio"
android:foreground="?android:attr/selectableItemBackground"
android:checked="false"
android:gravity="center"
android:textColor="@color/filter_dialog_button_text" />
android:textColor="@color/filter_dialog_button_text"
style="@style/NoButtonRadio" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<RadioButton
android:id="@+id/filter_dialog_clear"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/ic_filter_close"
style="@style/NoButtonRadio"
android:foreground="?android:attr/selectableItemBackground"
android:layout_gravity="center_vertical"
android:checked="true" />
android:checked="true"
style="@style/NoButtonRadio" />
</de.danoeh.antennapod.ui.common.RecursiveRadioGroup>

View File

@ -1,9 +1,11 @@
package de.danoeh.antennapod.model.feed;
import android.text.TextUtils;
import java.io.Serializable;
import java.util.Arrays;
public class FeedItemFilter {
public class FeedItemFilter implements Serializable {
private final String[] properties;

View File

@ -6,6 +6,9 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import androidx.annotation.Nullable;
import java.util.ArrayList;
/**
@ -15,6 +18,8 @@ import java.util.ArrayList;
public class RecursiveRadioGroup extends LinearLayout {
private final ArrayList<RadioButton> radioButtons = new ArrayList<>();
private RadioButton checkedButton = null;
@Nullable
private RadioGroup.OnCheckedChangeListener checkedChangeListener;
public RecursiveRadioGroup(Context context) {
super(context);
@ -34,6 +39,10 @@ public class RecursiveRadioGroup extends LinearLayout {
parseChild(child);
}
public void setOnCheckedChangeListener(@Nullable RadioGroup.OnCheckedChangeListener listener) {
checkedChangeListener = listener;
}
public void parseChild(final View child) {
if (child instanceof RadioButton) {
RadioButton button = (RadioButton) child;
@ -43,6 +52,9 @@ public class RecursiveRadioGroup extends LinearLayout {
return;
}
checkedButton = (RadioButton) buttonView;
if (checkedChangeListener != null) {
checkedChangeListener.onCheckedChanged(null, checkedButton.getId());
}
for (RadioButton view : radioButtons) {
if (view != buttonView) {