mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-01-25 00:16:56 +00:00
searchfilters: Moving DividerItem from NewPipeExtractor into NewPipe
DividerItem was inserted in the content filter framework in the NewPipeExtractor to have a section title for YoutubeMusic. But as UI releated stuff seems a bit out of place in the Extractor I came up with injecting the DividerItem aka section title in the frontend without having to change too much in the frontend.
This commit is contained in:
parent
3c038aaf7c
commit
7c650f6e9d
@ -0,0 +1,147 @@
|
||||
package org.schabi.newpipe.fragments.list.search.filter;
|
||||
|
||||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.extractor.search.filter.FilterContainer;
|
||||
import org.schabi.newpipe.extractor.search.filter.FilterGroup;
|
||||
import org.schabi.newpipe.extractor.search.filter.FilterItem;
|
||||
import org.schabi.newpipe.extractor.search.filter.LibraryStringIds;
|
||||
import org.schabi.newpipe.extractor.services.youtube.search.filter.YoutubeFilters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Inject a {@link FilterItem} that actually should not be a real filter.
|
||||
* <p>
|
||||
* This base class is meant to inject eg {@link DividerItem} (that inherits {@link FilterItem})
|
||||
* as Divider between {@link FilterItem}. It will be shown in the UI's.
|
||||
* <p>
|
||||
* Of course you have to handle {@link DividerItem} or whatever in the Ui's.
|
||||
* For that for example have a look at {@link SearchFilterDialogSpinnerAdapter}.
|
||||
*/
|
||||
public abstract class InjectFilterItem {
|
||||
|
||||
protected InjectFilterItem(
|
||||
@NonNull final String serviceName,
|
||||
final int injectedAfterFilterWithId,
|
||||
@NonNull final FilterItem toBeInjectedFilterItem) {
|
||||
|
||||
prepareAndInject(serviceName, injectedAfterFilterWithId, toBeInjectedFilterItem);
|
||||
}
|
||||
|
||||
// Please refer a static boolean to determine if already injected
|
||||
protected abstract boolean isAlreadyInjected();
|
||||
|
||||
// Please refer a static boolean to determine if already injected
|
||||
protected abstract void setAsInjected();
|
||||
|
||||
private void prepareAndInject(
|
||||
@NonNull final String serviceName,
|
||||
final int injectedAfterFilterWithId,
|
||||
@NonNull final FilterItem toBeInjectedFilterItem) {
|
||||
|
||||
if (isAlreadyInjected()) { // already run
|
||||
return;
|
||||
}
|
||||
|
||||
try { // using serviceName to test if we are trying to inject into the right service
|
||||
final List<FilterGroup> groups = NewPipe.getService(serviceName)
|
||||
.getSearchQHFactory().getAvailableContentFilter().getFilterGroups();
|
||||
injectFilterItemIntoGroup(
|
||||
groups,
|
||||
injectedAfterFilterWithId,
|
||||
toBeInjectedFilterItem);
|
||||
setAsInjected();
|
||||
} catch (final ExtractionException ignored) {
|
||||
// no the service we want to prepareAndInject -> so ignore
|
||||
}
|
||||
}
|
||||
|
||||
private void injectFilterItemIntoGroup(
|
||||
@NonNull final List<FilterGroup> groups,
|
||||
final int injectedAfterFilterWithId,
|
||||
@NonNull final FilterItem toBeInjectedFilterItem) {
|
||||
|
||||
int indexForFilterId = 0;
|
||||
boolean isFilterItemFound = false;
|
||||
FilterGroup groupWithTheSearchFilterItem = null;
|
||||
|
||||
for (final FilterGroup group : groups) {
|
||||
for (final FilterItem item : group.getFilterItems()) {
|
||||
if (item.getIdentifier() == injectedAfterFilterWithId) {
|
||||
isFilterItemFound = true;
|
||||
break;
|
||||
}
|
||||
indexForFilterId++;
|
||||
}
|
||||
|
||||
if (isFilterItemFound) {
|
||||
groupWithTheSearchFilterItem = group;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isFilterItemFound) {
|
||||
// we want to insert after the FilterItem we've searched
|
||||
indexForFilterId++;
|
||||
groupWithTheSearchFilterItem.getFilterItems()
|
||||
.add(indexForFilterId, toBeInjectedFilterItem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject DividerItem between YouTube content filters and YoutubeMusic content filters.
|
||||
*/
|
||||
public static class DividerBetweenYoutubeAndYoutubeMusic extends InjectFilterItem {
|
||||
|
||||
private static boolean isYoutubeMusicDividerInjected = false;
|
||||
|
||||
protected DividerBetweenYoutubeAndYoutubeMusic() {
|
||||
super(App.getApp().getApplicationContext().getString(R.string.youtube),
|
||||
YoutubeFilters.ID_CF_MAIN_PLAYLISTS,
|
||||
new DividerItem(R.string.search_filters_youtube_music)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Have a static runner method to avoid creating unnecessary objects if already inserted.
|
||||
*/
|
||||
public static void run() {
|
||||
if (!isYoutubeMusicDividerInjected) {
|
||||
new DividerBetweenYoutubeAndYoutubeMusic();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAlreadyInjected() {
|
||||
return isYoutubeMusicDividerInjected;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAsInjected() {
|
||||
isYoutubeMusicDividerInjected = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to have a title divider between regular {@link FilterItem}s.
|
||||
*/
|
||||
public static class DividerItem extends FilterItem {
|
||||
|
||||
private final int resId;
|
||||
|
||||
public DividerItem(final int resId) {
|
||||
// the LibraryStringIds.. is not needed at all I just need one to satisfy FilterItem.
|
||||
super(FilterContainer.ITEM_IDENTIFIER_UNKNOWN, LibraryStringIds.SEARCH_FILTERS_ALL);
|
||||
this.resId = resId;
|
||||
}
|
||||
|
||||
public int getStringResId() {
|
||||
return this.resId;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package org.schabi.newpipe.filter;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.extractor.search.filter.FilterContainer;
|
||||
import org.schabi.newpipe.extractor.search.filter.FilterGroup;
|
||||
import org.schabi.newpipe.extractor.search.filter.FilterItem;
|
||||
import org.schabi.newpipe.extractor.services.youtube.search.filter.YoutubeFilters;
|
||||
import org.schabi.newpipe.fragments.list.search.filter.InjectFilterItem;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class InjectFilterItemTest {
|
||||
|
||||
static final String SERVICE_NAME = "YouTube";
|
||||
|
||||
@Test
|
||||
public void injectIntoFilterGroupTest() throws ExtractionException {
|
||||
final FilterContainer filterContainer = NewPipe.getService(SERVICE_NAME)
|
||||
.getSearchQHFactory().getAvailableContentFilter();
|
||||
|
||||
final AtomicInteger itemCount = new AtomicInteger();
|
||||
assertFalse(getInjectedFilterItem(filterContainer, itemCount).isPresent());
|
||||
|
||||
InjectDividerTestClass.run(SERVICE_NAME);
|
||||
|
||||
final int expectedInjectedItemPosition = 5;
|
||||
final AtomicInteger injectedItemPosition = new AtomicInteger();
|
||||
assertTrue(getInjectedFilterItem(filterContainer, injectedItemPosition).isPresent());
|
||||
assertTrue(itemCount.get() > injectedItemPosition.get());
|
||||
assertEquals(expectedInjectedItemPosition, injectedItemPosition.get());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Optional<FilterItem> getInjectedFilterItem(
|
||||
@NonNull final FilterContainer filterContainer,
|
||||
@NonNull final AtomicInteger itemCount) {
|
||||
|
||||
return filterContainer.getFilterGroups().stream()
|
||||
.map(FilterGroup::getFilterItems)
|
||||
.flatMap(Collection::stream)
|
||||
.filter(item -> {
|
||||
itemCount.getAndIncrement();
|
||||
return item instanceof InjectFilterItem.DividerItem;
|
||||
})
|
||||
.findAny();
|
||||
}
|
||||
|
||||
public static class InjectDividerTestClass extends InjectFilterItem {
|
||||
|
||||
private static boolean isDividerInjected = false;
|
||||
|
||||
protected InjectDividerTestClass(@NonNull final String serviceName) {
|
||||
super(serviceName,
|
||||
YoutubeFilters.ID_CF_MAIN_PLAYLISTS,
|
||||
new DividerItem(0)
|
||||
);
|
||||
}
|
||||
|
||||
public static void run(final String serviceName) {
|
||||
if (!isDividerInjected) {
|
||||
new InjectDividerTestClass(serviceName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAlreadyInjected() {
|
||||
return isDividerInjected;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAsInjected() {
|
||||
isDividerInjected = true;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user