From 2e6a04046512dc464c40b4c10dbbbeac9b33fe90 Mon Sep 17 00:00:00 2001 From: Christine Emrich Date: Tue, 29 May 2018 20:49:14 +0200 Subject: [PATCH] Refactor pillow buttons into their own fragment --- .../app/mediathek/api/request/Interval.java | 12 ++ .../mediathek/api/request/QueryRequest.java | 14 +- .../api/request/query/IntervalList.java | 14 ++ .../ui/list/MediathekListFilterFragment.java | 90 ++------ .../ui/list/MediathekListFragment.java | 10 + .../view/PillowButtonScrollerFragment.java | 195 ++++++++++++++++++ .../layout/fragment_mediathek_list_filter.xml | 44 ++-- .../fragment_pillow_button_scroller.xml | 17 ++ ..._pillow_button_scroller_toggle_button.xml} | 0 app/src/main/res/values/arrays.xml | 18 +- app/src/main/res/values/attrs.xml | 6 + app/src/main/res/values/strings.xml | 5 + 12 files changed, 325 insertions(+), 100 deletions(-) create mode 100644 app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/Interval.java create mode 100644 app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/query/IntervalList.java create mode 100644 app/src/main/java/de/christinecoenen/code/zapp/utils/view/PillowButtonScrollerFragment.java create mode 100644 app/src/main/res/layout/fragment_pillow_button_scroller.xml rename app/src/main/res/layout/{fragment_mediathek_list_filter_toggle_button.xml => fragment_pillow_button_scroller_toggle_button.xml} (100%) diff --git a/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/Interval.java b/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/Interval.java new file mode 100644 index 00000000..65d79ddd --- /dev/null +++ b/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/Interval.java @@ -0,0 +1,12 @@ +package de.christinecoenen.code.zapp.app.mediathek.api.request; + +public class Interval { + + private int start; + private int end; + + public Interval(int start, int end) { + this.start = start; + this.end = end; + } +} diff --git a/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/QueryRequest.java b/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/QueryRequest.java index 8c3cc4a8..5f60a1df 100644 --- a/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/QueryRequest.java +++ b/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/QueryRequest.java @@ -27,10 +27,13 @@ public class QueryRequest implements Serializable { private final transient TextQuery searchQuery = new TextQuery() .addField(Field.TITLE) .addField(Field.TOPIC); + private final transient RangeQuery lengthQuery = new RangeQuery() + .setField(Field.DURATION) + .setGte("0"); private final BoolQuery body = new BoolQuery() .setNotQueries(EXCLUDE_CHANNELS_QUERY) - .setMustQueries(noSearchQuery) + .setMustQueries(noSearchQuery, lengthQuery) .setFilterQueries(EXCLUDE_FUTURE_QUERY); private List sort; @@ -39,14 +42,19 @@ public class QueryRequest implements Serializable { public QueryRequest setSimpleSearch(String queryString) { if (TextUtils.isEmpty(queryString)) { - body.setMustQueries(noSearchQuery); + body.setMustQueries(noSearchQuery, lengthQuery); } else { searchQuery.setText(queryString); - body.setMustQueries(searchQuery); + body.setMustQueries(searchQuery, lengthQuery); } return this; } + public QueryRequest setMinLength(int minLengthSeconds) { + lengthQuery.setGte(String.valueOf(minLengthSeconds)); + return this; + } + public QueryRequest excludeChannels(String... channels) { TextQuery[] dynamicExcludeChannelQueries = new TextQuery[channels.length + 1]; int i = 0; diff --git a/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/query/IntervalList.java b/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/query/IntervalList.java new file mode 100644 index 00000000..ca6483cd --- /dev/null +++ b/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/api/request/query/IntervalList.java @@ -0,0 +1,14 @@ +package de.christinecoenen.code.zapp.app.mediathek.api.request.query; + +import java.util.ArrayList; +import java.util.List; + +import de.christinecoenen.code.zapp.app.mediathek.api.request.Interval; + +public class IntervalList { + + private List intervals = new ArrayList<>(); + + //public + +} diff --git a/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/ui/list/MediathekListFilterFragment.java b/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/ui/list/MediathekListFilterFragment.java index 1d50f9a5..d4ef91c0 100644 --- a/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/ui/list/MediathekListFilterFragment.java +++ b/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/ui/list/MediathekListFilterFragment.java @@ -9,31 +9,23 @@ import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.ToggleButton; import java.util.ArrayList; import java.util.Objects; -import butterknife.BindArray; -import butterknife.BindView; import butterknife.ButterKnife; import de.christinecoenen.code.zapp.R; +import de.christinecoenen.code.zapp.utils.view.PillowButtonScrollerFragment; public class MediathekListFilterFragment extends Fragment { private static final String SHARED_PREFS_KEY_FILTER_OPEN = "SHARED_PREFS_FRILTER_OPEN"; - private static final String SHARED_PREFS_KEY_FILTER_CHANNEL_SELECTED_ = "SHARED_PREFS_KEY_FILTER_CHANNEL_SELECTED_"; - - @BindArray(R.array.mediathek_channels) - protected String[] channelNames; - - @BindView(R.id.container_channel_buttons) - protected LinearLayout channelButtonContainer; private Listener listener; private SharedPreferences sharedPreferences; + private PillowButtonScrollerFragment channelFilter; + private PillowButtonScrollerFragment lengthFilter; public MediathekListFilterFragment() { // Required empty public constructor @@ -52,16 +44,12 @@ public class MediathekListFilterFragment extends Fragment { } public String[] getExcludedChannels() { - ArrayList excludedChannels = new ArrayList<>(); + return channelFilter.getExcludedKeys(); + } - for (int i = 0; i < channelButtonContainer.getChildCount(); i++) { - ToggleButton channelButton = (ToggleButton) channelButtonContainer.getChildAt(i); - if (!channelButton.isChecked()) { - excludedChannels.add(channelButton.getText().toString()); - } - } - - return excludedChannels.toArray(new String[excludedChannels.size()]); + public int getMinLength() { + // TODO: expose length intervals + return 0; } @Override @@ -75,9 +63,13 @@ public class MediathekListFilterFragment extends Fragment { View view = inflater.inflate(R.layout.fragment_mediathek_list_filter, container, false); ButterKnife.bind(this, view); - for (String channelName : channelNames) { - addChannelButton(inflater, channelName); - } + channelFilter = (PillowButtonScrollerFragment) getChildFragmentManager() + .findFragmentById(R.id.fragment_channel_filter); + channelFilter.setListener(() -> listener.onChannelsChanged()); + + lengthFilter = (PillowButtonScrollerFragment) getChildFragmentManager() + .findFragmentById(R.id.fragment_length_filter); + lengthFilter.setListener(() -> listener.onLengthChanged()); return view; } @@ -131,57 +123,9 @@ public class MediathekListFilterFragment extends Fragment { sharedPreferences.edit().putBoolean(SHARED_PREFS_KEY_FILTER_OPEN, false).apply(); } - private void addChannelButton(LayoutInflater inflater, String channelName) { - ToggleButton channelButton = (ToggleButton) inflater.inflate( - R.layout.fragment_mediathek_list_filter_toggle_button, - channelButtonContainer, false); - channelButton.setTextOff(channelName); - channelButton.setTextOn(channelName); - - boolean isChecked = sharedPreferences.getBoolean(SHARED_PREFS_KEY_FILTER_CHANNEL_SELECTED_ + channelName, true); - channelButton.setChecked(isChecked); - - channelButton.setOnClickListener(v -> onChannelButtonClicked((ToggleButton) v, channelName)); - channelButton.setOnLongClickListener(v -> onChannelButtonLongClicked((ToggleButton) v, channelName)); - channelButtonContainer.addView(channelButton); - } - - private void onChannelButtonClicked(ToggleButton button, String channelName) { - setChannelButton(button, channelName, button.isChecked()); - - if (listener != null) { - listener.onChannelsChanged(); - } - } - - private boolean onChannelButtonLongClicked(ToggleButton button, String channelName) { - boolean isOnlyOneChecked = getExcludedChannels().length >= channelButtonContainer.getChildCount() - 1; - boolean doOthersCheck = button.isChecked() && isOnlyOneChecked; - - for (int i = 0; i < channelButtonContainer.getChildCount(); i++) { - ToggleButton channelButton = (ToggleButton) channelButtonContainer.getChildAt(i); - if (channelButton != button) { - setChannelButton(channelButton, channelButton.getTextOn().toString(), doOthersCheck); - } - } - setChannelButton(button, channelName, true); - - if (listener != null) { - listener.onChannelsChanged(); - } - - return true; - } - - private void setChannelButton(ToggleButton button, String channelName, boolean checked) { - sharedPreferences - .edit() - .putBoolean(SHARED_PREFS_KEY_FILTER_CHANNEL_SELECTED_ + channelName, checked) - .apply(); - button.setChecked(checked); - } - public interface Listener { + void onLengthChanged(); + void onChannelsChanged(); } } diff --git a/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/ui/list/MediathekListFragment.java b/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/ui/list/MediathekListFragment.java index 182d4f2a..dd484526 100644 --- a/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/ui/list/MediathekListFragment.java +++ b/app/src/main/java/de/christinecoenen/code/zapp/app/mediathek/ui/list/MediathekListFragment.java @@ -212,6 +212,16 @@ public class MediathekListFragment extends Fragment implements loadItems(0, true); } + @Override + public void onLengthChanged() { + setMinLengthFilter(); + loadItems(0, true); + } + + private void setMinLengthFilter() { + queryRequest.setMinLength(filter.getMinLength() * 60); + } + private void setChannelFilter() { queryRequest.excludeChannels(filter.getExcludedChannels()); } diff --git a/app/src/main/java/de/christinecoenen/code/zapp/utils/view/PillowButtonScrollerFragment.java b/app/src/main/java/de/christinecoenen/code/zapp/utils/view/PillowButtonScrollerFragment.java new file mode 100644 index 00000000..6aeee61c --- /dev/null +++ b/app/src/main/java/de/christinecoenen/code/zapp/utils/view/PillowButtonScrollerFragment.java @@ -0,0 +1,195 @@ +package de.christinecoenen.code.zapp.utils.view; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.TypedArray; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.ToggleButton; + +import java.util.ArrayList; +import java.util.Objects; + +import butterknife.BindView; +import butterknife.ButterKnife; +import de.christinecoenen.code.zapp.R; + +public class PillowButtonScrollerFragment extends Fragment { + private static final String ARG_SHARED_PREFS_PREFIX = "ARG_SHARED_PREFS_PREFIX"; + private static final String ARG_KEY_LIST = "ARG_KEY_LIST"; + private static final String ARG_LABEL_LIST = "ARG_LABEL_LIST"; + + + @BindView(R.id.container_toggle_buttons) + protected LinearLayout buttonContainer; + + + private String sharedPrefsPrefix; + private String[] keyList; + private String[] labelList; + + private Listener listener; + private SharedPreferences sharedPreferences; + + public PillowButtonScrollerFragment() { + // Required empty public constructor + } + + public static PillowButtonScrollerFragment newInstance(String sharedPrefsPrefix, String[] keyList, String[] labelList) { + PillowButtonScrollerFragment fragment = new PillowButtonScrollerFragment(); + Bundle args = new Bundle(); + args.putString(ARG_SHARED_PREFS_PREFIX, sharedPrefsPrefix); + args.putStringArray(ARG_KEY_LIST, keyList); + args.putStringArray(ARG_LABEL_LIST, labelList); + fragment.setArguments(args); + return fragment; + } + + public String[] getExcludedKeys() { + ArrayList excludedKeys = new ArrayList<>(); + + for (int i = 0; i < buttonContainer.getChildCount(); i++) { + ToggleButton button = (ToggleButton) buttonContainer.getChildAt(i); + if (!button.isChecked()) { + excludedKeys.add(keyList[i]); + } + } + + return excludedKeys.toArray(new String[excludedKeys.size()]); + } + + public String[] getIncludedKeys() { + ArrayList includedKeys = new ArrayList<>(); + + for (int i = 0; i < buttonContainer.getChildCount(); i++) { + ToggleButton button = (ToggleButton) buttonContainer.getChildAt(i); + if (button.isChecked()) { + includedKeys.add(keyList[i]); + } + } + + return includedKeys.toArray(new String[includedKeys.size()]); + } + + public void setListener(Listener listener) { + this.listener = listener; + } + + @Override + public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) { + super.onInflate(context, attrs, savedInstanceState); + + TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.PillowButtonScrollerFragment); + + int keyListResId = attributes.getResourceId(R.styleable.PillowButtonScrollerFragment_key_list_res_id, 0); + int labelListResId = attributes.getResourceId(R.styleable.PillowButtonScrollerFragment_label_list_res_id, 0); + sharedPrefsPrefix = attributes.getString(R.styleable.PillowButtonScrollerFragment_shared_prefs_prefix); + + if (keyListResId == 0 || labelListResId == 0 || sharedPrefsPrefix == null) { + throw new IllegalArgumentException("shared_prefs_prefix, key_list_res_id and label_list_res_id habe to set in xml layout"); + } + + keyList = getResources().getStringArray(keyListResId); + labelList = getResources().getStringArray(labelListResId); + + attributes.recycle(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + sharedPrefsPrefix = getArguments().getString(ARG_SHARED_PREFS_PREFIX); + keyList = getArguments().getStringArray(ARG_KEY_LIST); + labelList = getArguments().getStringArray(ARG_LABEL_LIST); + } + + sharedPreferences = Objects.requireNonNull(getActivity()).getPreferences(Context.MODE_PRIVATE); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_pillow_button_scroller, container, false); + ButterKnife.bind(this, view); + + for (int i = 0; i< labelList.length; i++) { + addButton(inflater, i); + } + + return view; + } + + @Override + public void onDetach() { + super.onDetach(); + listener = null; + } + + private void addButton(LayoutInflater inflater, int index) { + String label = labelList[index]; + String key = labelList[index]; + + ToggleButton channelButton = (ToggleButton) inflater.inflate( + R.layout.fragment_pillow_button_scroller_toggle_button, + buttonContainer, false); + channelButton.setTextOff(label); + channelButton.setTextOn(label); + channelButton.setTag(index); + + boolean isChecked = sharedPreferences.getBoolean(sharedPrefsPrefix + "_" + key, true); + channelButton.setChecked(isChecked); + + channelButton.setOnClickListener(this::onButtonClicked); + channelButton.setOnLongClickListener(this::onButtonLongClicked); + buttonContainer.addView(channelButton); + } + + private void onButtonClicked(View view) { + ToggleButton button = (ToggleButton) view; + setChannelButton(button, button.isChecked()); + + if (listener != null) { + listener.onValuesChanged(); + } + } + + private boolean onButtonLongClicked(View view) { + ToggleButton button = (ToggleButton) view; + boolean isOnlyOneChecked = getIncludedKeys().length <= 1; + boolean doOthersCheck = button.isChecked() && isOnlyOneChecked; + + for (int i = 0; i < buttonContainer.getChildCount(); i++) { + ToggleButton channelButton = (ToggleButton) buttonContainer.getChildAt(i); + if (channelButton != button) { + setChannelButton(channelButton, doOthersCheck); + } + } + setChannelButton(button, true); + + if (listener != null) { + listener.onValuesChanged(); + } + + return true; + } + + private void setChannelButton(ToggleButton button, boolean checked) { + int index = (int) button.getTag(); + + sharedPreferences + .edit() + .putBoolean(sharedPrefsPrefix + "_" + keyList[index], checked) + .apply(); + + button.setChecked(checked); + } + + public interface Listener { + void onValuesChanged(); + } +} diff --git a/app/src/main/res/layout/fragment_mediathek_list_filter.xml b/app/src/main/res/layout/fragment_mediathek_list_filter.xml index e64f4fc9..373381a7 100644 --- a/app/src/main/res/layout/fragment_mediathek_list_filter.xml +++ b/app/src/main/res/layout/fragment_mediathek_list_filter.xml @@ -28,54 +28,52 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/fragment_mediathek_filter_duration" - android:visibility="gone" - app:layout_constraintStart_toStartOf="parent" /> + app:layout_constraintBottom_toBottomOf="@+id/fragment_length_filter" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="@+id/fragment_length_filter" /> - + app:layout_constraintTop_toBottomOf="@+id/fragment_channel_filter" + app:shared_prefs_prefix="SHARED_PREFS_KEY_FILTER_LENGTH_SELECTED" /> + app:constraint_referenced_ids="label_duration,fragment_length_filter" /> + app:layout_constraintTop_toTopOf="@id/fragment_channel_filter" /> - - - - - + app:layout_constraintTop_toTopOf="parent" + app:shared_prefs_prefix="SHARED_PREFS_KEY_FILTER_CHANNEL_SELECTED" /> diff --git a/app/src/main/res/layout/fragment_pillow_button_scroller.xml b/app/src/main/res/layout/fragment_pillow_button_scroller.xml new file mode 100644 index 00000000..df2bbdb7 --- /dev/null +++ b/app/src/main/res/layout/fragment_pillow_button_scroller.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/app/src/main/res/layout/fragment_mediathek_list_filter_toggle_button.xml b/app/src/main/res/layout/fragment_pillow_button_scroller_toggle_button.xml similarity index 100% rename from app/src/main/res/layout/fragment_mediathek_list_filter_toggle_button.xml rename to app/src/main/res/layout/fragment_pillow_button_scroller_toggle_button.xml diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index fe8ea3a9..744854c3 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -2,7 +2,7 @@ - + ARD ZDF BR @@ -24,4 +24,20 @@ SRF.Podcast + + 0_6 + 6_15 + 15_35 + 35_65 + 65_1000 + + + + @string/fragment_mediathek_length_label_0 + @string/fragment_mediathek_length_label_1 + @string/fragment_mediathek_length_label_2 + @string/fragment_mediathek_length_label_3 + @string/fragment_mediathek_length_label_4 + + diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 605b5bf8..9f624796 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -9,4 +9,10 @@ + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 727c3306..9f697fe6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -38,6 +38,11 @@ Dauer Sender + 0–6m + 6–15m + 15–35m + 35–65m + 65+ Download von \'%s\' gestartet…