diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java index 5175e0096..ce0334135 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java @@ -3,7 +3,6 @@ package org.schabi.newpipe.fragments.list.search; import static androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags; import static org.schabi.newpipe.ktx.ViewUtils.animate; import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView; -import static java.util.Arrays.asList; import android.app.Activity; import android.content.Context; @@ -34,10 +33,13 @@ import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.TooltipCompat; import androidx.core.text.HtmlCompat; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.FragmentManager; import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; +import org.schabi.newpipe.App; import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.FragmentSearchBinding; import org.schabi.newpipe.error.ErrorInfo; @@ -50,12 +52,15 @@ import org.schabi.newpipe.extractor.MetaInfo; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.search.SearchInfo; -import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeSearchQueryHandlerFactory; -import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory; +import org.schabi.newpipe.extractor.search.filter.FilterItem; import org.schabi.newpipe.fragments.BackPressable; import org.schabi.newpipe.fragments.list.BaseListFragment; +import org.schabi.newpipe.fragments.list.search.filter.BaseSearchFilterDialogFragment; +import org.schabi.newpipe.fragments.list.search.filter.SearchFilterDialogFragment; +import org.schabi.newpipe.fragments.list.search.filter.SearchFilterLogic; import org.schabi.newpipe.ktx.AnimationType; import org.schabi.newpipe.ktx.ExceptionUtils; import org.schabi.newpipe.local.history.HistoryRecordManager; @@ -65,14 +70,11 @@ import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.KeyboardUtil; import org.schabi.newpipe.util.NavigationHelper; -import org.schabi.newpipe.util.ServiceHelper; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Queue; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -87,7 +89,8 @@ import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.PublishSubject; public class SearchFragment extends BaseListFragment> - implements BackPressable { + implements BackPressable, SearchFilterLogic.Callback, + BaseSearchFilterDialogFragment.Listener { /*////////////////////////////////////////////////////////////////////////// // Search //////////////////////////////////////////////////////////////////////////*/ @@ -105,9 +108,6 @@ public class SearchFragment extends BaseListFragment suggestionPublisher = PublishSubject.create(); - @State - int filterItemCheckedId = -1; - @State protected int serviceId = Constants.NO_SERVICE_ID; @@ -115,15 +115,9 @@ public class SearchFragment extends BaseListFragment selectedContentFilter = new ArrayList<>(); - @State - String sortFilter; + List selectedSortFilter = new ArrayList<>(); // these represents the last search @State @@ -141,7 +135,6 @@ public class SearchFragment extends BaseListFragment menuItemToFilterName = null; private StreamingService service; private Page nextPage; private boolean showLocalSuggestions = true; @@ -170,9 +163,15 @@ public class SearchFragment extends BaseListFragment userSelectedContentFilterList; + + @State + ArrayList userSelectedSortFilterList = null; + public static SearchFragment getInstance(final int serviceId, final String searchString) { final SearchFragment searchFragment = new SearchFragment(); - searchFragment.setQuery(serviceId, searchString, new String[0], ""); + searchFragment.setQuery(serviceId, searchString, null, null); if (!TextUtils.isEmpty(searchString)) { searchFragment.setSearchOnResume(); @@ -205,11 +204,44 @@ public class SearchFragment extends BaseListFragment(); + } + + if (userSelectedSortFilterList == null) { + userSelectedSortFilterList = new ArrayList<>(); + } + initializeFilterData(); + updateService(); return inflater.inflate(R.layout.fragment_search, container, false); } + /** + * initialize the initial content and sort filter Lists with defaults + * or previously with Icepick stored data. + */ + protected void initializeFilterData() { + try { + final SearchFilterLogic logic = + new SearchFilterLogic(NewPipe.getService(serviceId).getSearchQHFactory(), null); + logic.restorePreviouslySelectedFilters( + userSelectedContentFilterList, + userSelectedSortFilterList); + + userSelectedContentFilterList = logic.getSelectedContentFilters(); + userSelectedSortFilterList = logic.getSelectedSortFilters(); + selectedContentFilter = logic.getSelectedContentFilterItems(); + selectedSortFilter = logic.getSelectedSortFiltersItems(); + } catch (final ExtractionException e) { + ErrorUtil.showUiErrorSnackbar(this, + "No filtering possible. Getting service for id " + serviceId, e); + } + } + @Override public void onViewCreated(@NonNull final View rootView, final Bundle savedInstanceState) { searchBinding = FragmentSearchBinding.bind(rootView); @@ -265,11 +297,11 @@ public class SearchFragment extends BaseListFragment(); - - int itemId = 0; - boolean isFirstItem = true; - final Context c = getContext(); - if (service == null) { Log.w(TAG, "onCreateOptionsMenu() called with null service"); updateService(); } - for (final String filter : service.getSearchQHFactory().getAvailableContentFilter()) { - if (filter.equals(YoutubeSearchQueryHandlerFactory.MUSIC_SONGS)) { - final MenuItem musicItem = menu.add(2, - itemId++, - 0, - "YouTube Music"); - musicItem.setEnabled(false); - } else if (filter.equals(PeertubeSearchQueryHandlerFactory.SEPIA_VIDEOS)) { - final MenuItem sepiaItem = menu.add(2, - itemId++, - 0, - "Sepia Search"); - sepiaItem.setEnabled(false); - } - menuItemToFilterName.put(itemId, filter); - final MenuItem item = menu.add(1, - itemId++, - 0, - ServiceHelper.getTranslatedFilterString(filter, c)); - if (isFirstItem) { - item.setChecked(true); - isFirstItem = false; - } - } - menu.setGroupCheckable(1, true, true); + createMenu(menu, inflater); + } - restoreFilterChecked(menu, filterItemCheckedId); + protected void createMenu(@NonNull final Menu menu, + @NonNull final MenuInflater inflater) { + inflater.inflate(R.menu.menu_search_fragment, menu); } @Override public boolean onOptionsItemSelected(@NonNull final MenuItem item) { - if (menuItemToFilterName != null) { - final List cf = new ArrayList<>(1); - cf.add(menuItemToFilterName.get(item.getItemId())); - changeContentFilter(item, cf); + if (item.getItemId() == R.id.action_filter) { + hideKeyboardSearch(); + showSelectFiltersDialog(); + return false; } return true; } - private void restoreFilterChecked(final Menu menu, final int itemId) { - if (itemId != -1) { - final MenuItem item = menu.findItem(itemId); - if (item == null) { - return; - } - - item.setChecked(true); - } - } - /*////////////////////////////////////////////////////////////////////////// // Search //////////////////////////////////////////////////////////////////////////*/ @@ -564,7 +559,7 @@ public class SearchFragment extends BaseListFragment theContentFilter, + final List theSortFilter) { if (DEBUG) { Log.d(TAG, "search() called with: query = [" + theSearchString + "]"); } @@ -862,13 +857,12 @@ public class SearchFragment extends BaseListFragment isLoading.set(false)) .subscribe(this::handleResult, this::onItemError); - } @Override @@ -884,8 +878,8 @@ public class SearchFragment extends BaseListFragment theContentFilter) { - filterItemCheckedId = item.getItemId(); - item.setChecked(true); + @Override + public void selectedFilters(final List theSelectedContentFilter, + final List theSelectedSortFilter) { - contentFilter = theContentFilter.toArray(new String[0]); + selectedContentFilter = theSelectedContentFilter; + selectedSortFilter = theSelectedSortFilter; if (!TextUtils.isEmpty(searchString)) { - search(searchString, contentFilter, sortFilter); + search(searchString, selectedContentFilter, selectedSortFilter); } } private void setQuery(final int theServiceId, final String theSearchString, - final String[] theContentFilter, - final String theSortFilter) { + final List theContentFilter, + final List theSortFilter) { serviceId = theServiceId; searchString = theSearchString; - contentFilter = theContentFilter; - sortFilter = theSortFilter; } /*////////////////////////////////////////////////////////////////////////// @@ -1020,7 +1013,7 @@ public class SearchFragment extends BaseListFragment { searchBinding.correctSuggestion.setVisibility(View.GONE); - search(searchSuggestion, contentFilter, sortFilter); + search(searchSuggestion, selectedContentFilter, selectedSortFilter); searchEditText.setText(searchSuggestion); }); @@ -1085,4 +1078,23 @@ public class SearchFragment extends BaseListFragment userSelectedContentFilterList, + final ArrayList userSelectedSortFilterList, + final List selectedContentFilters, + final List selectedSortFilters) { + selectedFilters(selectedContentFilters, selectedSortFilters); + } } diff --git a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java index 27009efd1..e4f19dff6 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java @@ -26,6 +26,8 @@ import android.util.Log; import android.view.View; import android.widget.TextView; +import org.schabi.newpipe.extractor.search.filter.FilterItem; + import androidx.annotation.Nullable; import androidx.core.text.HtmlCompat; import androidx.preference.PreferenceManager; @@ -75,8 +77,8 @@ public final class ExtractorHelper { } public static Single searchFor(final int serviceId, final String searchString, - final List contentFilter, - final String sortFilter) { + final List contentFilter, + final List sortFilter) { checkServiceId(serviceId); return Single.fromCallable(() -> SearchInfo.getInfo(NewPipe.getService(serviceId), @@ -88,8 +90,8 @@ public final class ExtractorHelper { public static Single> getMoreSearchItems( final int serviceId, final String searchString, - final List contentFilter, - final String sortFilter, + final List contentFilter, + final List sortFilter, final Page page) { checkServiceId(serviceId); return Single.fromCallable(() -> diff --git a/app/src/main/res/menu/menu_search_fragment.xml b/app/src/main/res/menu/menu_search_fragment.xml new file mode 100644 index 000000000..1461245a5 --- /dev/null +++ b/app/src/main/res/menu/menu_search_fragment.xml @@ -0,0 +1,9 @@ + + + +