Merge branch 'search' into dev

This commit is contained in:
Christian Schabesberger 2018-07-19 16:19:33 +02:00
commit 3a44e92432
18 changed files with 428 additions and 267 deletions

View File

@ -54,7 +54,7 @@ dependencies {
exclude module: 'support-annotations' exclude module: 'support-annotations'
} }
implementation 'com.github.TeamNewPipe:NewPipeExtractor:bf1c771' implementation 'com.github.TeamNewPipe:NewPipeExtractor:1eff8c5708'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.8.9' testImplementation 'org.mockito:mockito-core:2.8.9'

View File

@ -61,6 +61,8 @@ import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.StateSaver; import org.schabi.newpipe.util.StateSaver;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import static org.schabi.newpipe.extractor.InfoItem.InfoType.PLAYLIST;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity"; private static final String TAG = "MainActivity";
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release"); public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
@ -392,31 +394,45 @@ public class MainActivity extends AppCompatActivity {
} }
private void handleIntent(Intent intent) { private void handleIntent(Intent intent) {
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]"); try {
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
if (intent.hasExtra(Constants.KEY_LINK_TYPE)) { if (intent.hasExtra(Constants.KEY_LINK_TYPE)) {
String url = intent.getStringExtra(Constants.KEY_URL); String url = intent.getStringExtra(Constants.KEY_URL);
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0); int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
String title = intent.getStringExtra(Constants.KEY_TITLE); String title = intent.getStringExtra(Constants.KEY_TITLE);
switch (((StreamingService.LinkType) intent.getSerializableExtra(Constants.KEY_LINK_TYPE))) { switch (((StreamingService.LinkType) intent.getSerializableExtra(Constants.KEY_LINK_TYPE))) {
case STREAM: case STREAM:
boolean autoPlay = intent.getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false); boolean autoPlay = intent.getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false);
NavigationHelper.openVideoDetailFragment(getSupportFragmentManager(), serviceId, url, title, autoPlay); NavigationHelper.openVideoDetailFragment(getSupportFragmentManager(), serviceId, url, title, autoPlay);
break; break;
case CHANNEL: case CHANNEL:
NavigationHelper.openChannelFragment(getSupportFragmentManager(), serviceId, url, title); NavigationHelper.openChannelFragment(getSupportFragmentManager(),
break; serviceId,
case PLAYLIST: url,
NavigationHelper.openPlaylistFragment(getSupportFragmentManager(), serviceId, url, title); title);
break; break;
case PLAYLIST:
NavigationHelper.openPlaylistFragment(getSupportFragmentManager(),
serviceId,
url,
title);
break;
}
} else if (intent.hasExtra(Constants.KEY_OPEN_SEARCH)) {
String searchString = intent.getStringExtra(Constants.KEY_SEARCH_STRING);
if (searchString == null) searchString = "";
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
NavigationHelper.openSearchFragment(
getSupportFragmentManager(),
serviceId,
searchString);
} else {
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
} }
} else if (intent.hasExtra(Constants.KEY_OPEN_SEARCH)) { } catch (Exception e) {
String searchQuery = intent.getStringExtra(Constants.KEY_QUERY); ErrorActivity.reportUiError(this, e);
if (searchQuery == null) searchQuery = "";
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
NavigationHelper.openSearchFragment(getSupportFragmentManager(), serviceId, searchQuery);
} else {
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
} }
} }
} }

View File

@ -10,6 +10,7 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -127,7 +128,14 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_search: case R.id.action_search:
NavigationHelper.openSearchFragment(getFragmentManager(), ServiceHelper.getSelectedServiceId(activity), ""); try {
NavigationHelper.openSearchFragment(
getFragmentManager(),
ServiceHelper.getSelectedServiceId(activity),
"");
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
return true; return true;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
@ -226,7 +234,9 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
FALLBACK_CHANNEL_URL); FALLBACK_CHANNEL_URL);
String name = preferences.getString(getString(R.string.main_page_selected_channel_name), String name = preferences.getString(getString(R.string.main_page_selected_channel_name),
FALLBACK_CHANNEL_NAME); FALLBACK_CHANNEL_NAME);
ChannelFragment fragment = ChannelFragment.getInstance(serviceId, url, name); ChannelFragment fragment = ChannelFragment.getInstance(serviceId,
url,
name);
fragment.useAsFrontPage(true); fragment.useAsFrontPage(true);
return fragment; return fragment;
} else { } else {
@ -255,20 +265,13 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
for (final String ks : kl.getAvailableKiosks()) { for (final String ks : kl.getAvailableKiosks()) {
menu.add(0, KIOSK_MENU_OFFSET + i, Menu.NONE, menu.add(0, KIOSK_MENU_OFFSET + i, Menu.NONE,
KioskTranslator.getTranslatedKioskName(ks, getContext())) KioskTranslator.getTranslatedKioskName(ks, getContext()))
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { .setOnMenuItemClickListener(menuItem -> {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
try { try {
NavigationHelper.openKioskFragment(getFragmentManager(), currentServiceId, ks); NavigationHelper.openKioskFragment(getFragmentManager(), currentServiceId, ks);
} catch (Exception e) { } catch (Exception e) {
ErrorActivity.reportError(activity, e, ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
activity.getClass(),
null,
ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
"none", "", R.string.app_ui_crash));
} }
return true; return true;
}
}); });
i++; i++;
} }

View File

@ -17,6 +17,7 @@ import android.support.v4.content.ContextCompat;
import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.Html; import android.text.Html;
import android.text.Spanned; import android.text.Spanned;
import android.text.TextUtils; import android.text.TextUtils;
@ -54,7 +55,7 @@ import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.stream.AudioStream; import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.Stream; import org.schabi.newpipe.extractor.stream.Stream;
import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfo;
@ -64,6 +65,7 @@ import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.fragments.BackPressable; import org.schabi.newpipe.fragments.BackPressable;
import org.schabi.newpipe.fragments.BaseStateFragment; import org.schabi.newpipe.fragments.BaseStateFragment;
import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.StreamItemAdapter; import org.schabi.newpipe.util.StreamItemAdapter;
import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper; import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
@ -365,11 +367,15 @@ public class VideoDetailFragment
if (TextUtils.isEmpty(currentInfo.getUploaderUrl())) { if (TextUtils.isEmpty(currentInfo.getUploaderUrl())) {
Log.w(TAG, "Can't open channel because we got no channel URL"); Log.w(TAG, "Can't open channel because we got no channel URL");
} else { } else {
NavigationHelper.openChannelFragment( try {
getFragmentManager(), NavigationHelper.openChannelFragment(
currentInfo.getServiceId(), getFragmentManager(),
currentInfo.getUploaderUrl(), currentInfo.getServiceId(),
currentInfo.getUploaderName()); currentInfo.getUploaderUrl(),
currentInfo.getUploaderName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
} }
break; break;
case R.id.detail_thumbnail_root_layout: case R.id.detail_thumbnail_root_layout:

View File

@ -6,6 +6,7 @@ import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.Log; import android.util.Log;
@ -24,6 +25,7 @@ import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.info_list.InfoItemDialog; import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.info_list.InfoListAdapter; import org.schabi.newpipe.info_list.InfoListAdapter;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture; import org.schabi.newpipe.util.OnClickGesture;
import org.schabi.newpipe.util.StateSaver; import org.schabi.newpipe.util.StateSaver;
@ -152,18 +154,35 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
infoListAdapter.setOnChannelSelectedListener(new OnClickGesture<ChannelInfoItem>() { infoListAdapter.setOnChannelSelectedListener(new OnClickGesture<ChannelInfoItem>() {
@Override @Override
public void selected(ChannelInfoItem selectedItem) { public void selected(ChannelInfoItem selectedItem) {
onItemSelected(selectedItem); try {
NavigationHelper.openChannelFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(), onItemSelected(selectedItem);
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName()); NavigationHelper.openChannelFragment(useAsFrontPage ?
getParentFragment().getFragmentManager()
: getFragmentManager(),
selectedItem.getServiceId(),
selectedItem.getUrl(),
selectedItem.getName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
} }
}); });
infoListAdapter.setOnPlaylistSelectedListener(new OnClickGesture<PlaylistInfoItem>() { infoListAdapter.setOnPlaylistSelectedListener(new OnClickGesture<PlaylistInfoItem>() {
@Override @Override
public void selected(PlaylistInfoItem selectedItem) { public void selected(PlaylistInfoItem selectedItem) {
onItemSelected(selectedItem); try {
NavigationHelper.openPlaylistFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(), onItemSelected(selectedItem);
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName()); NavigationHelper.openPlaylistFragment(
useAsFrontPage
? getParentFragment().getFragmentManager()
: getFragmentManager(),
selectedItem.getServiceId(),
selectedItem.getUrl(),
selectedItem.getName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
} }
}); });
@ -178,7 +197,9 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
private void onStreamSelected(StreamInfoItem selectedItem) { private void onStreamSelected(StreamInfoItem selectedItem) {
onItemSelected(selectedItem); onItemSelected(selectedItem);
NavigationHelper.openVideoDetailFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(), NavigationHelper.openVideoDetailFragment(useAsFrontPage
? getParentFragment().getFragmentManager()
: getFragmentManager(),
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName()); selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
} }

View File

@ -8,6 +8,9 @@ import android.view.View;
import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.ListInfo; import org.schabi.newpipe.extractor.ListInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.Constants;
import java.util.Queue; import java.util.Queue;
@ -166,7 +169,6 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
public void handleResult(@NonNull I result) { public void handleResult(@NonNull I result) {
super.handleResult(result); super.handleResult(result);
url = result.getUrl();
name = result.getName(); name = result.getName();
setTitle(name); setTitle(name);

View File

@ -33,6 +33,7 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelInfo; import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment; import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
import org.schabi.newpipe.info_list.InfoItemDialog; import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
@ -501,7 +502,11 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
if (super.onError(exception)) return true; if (super.onError(exception)) return true;
int errorId = exception instanceof ExtractionException ? R.string.parsing_error : R.string.general_error; int errorId = exception instanceof ExtractionException ? R.string.parsing_error : R.string.general_error;
onUnrecoverableError(exception, UserAction.REQUESTED_CHANNEL, NewPipe.getNameOfService(serviceId), url, errorId); onUnrecoverableError(exception,
UserAction.REQUESTED_CHANNEL,
NewPipe.getNameOfService(serviceId),
url,
errorId);
return true; return true;
} }

View File

@ -11,22 +11,20 @@ import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.kiosk.KioskInfo; import org.schabi.newpipe.extractor.kiosk.KioskInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment; import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.KioskTranslator; import org.schabi.newpipe.util.KioskTranslator;
import org.schabi.newpipe.util.NavigationHelper;
import icepick.State; import icepick.State;
import io.reactivex.Single; import io.reactivex.Single;
@ -74,10 +72,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
throws ExtractionException { throws ExtractionException {
KioskFragment instance = new KioskFragment(); KioskFragment instance = new KioskFragment();
StreamingService service = NewPipe.getService(serviceId); StreamingService service = NewPipe.getService(serviceId);
UrlIdHandler kioskTypeUrlIdHandler = service.getKioskList() ListLinkHandlerFactory kioskLinkHandlerFactory = service.getKioskList()
.getUrlIdHandlerByType(kioskId); .getListLinkHandlerFactoryByType(kioskId);
instance.setInitialData(serviceId, instance.setInitialData(serviceId,
kioskTypeUrlIdHandler.getUrl(kioskId), kioskId); kioskLinkHandlerFactory.fromId(kioskId).getUrl(), kioskId);
instance.kioskId = kioskId; instance.kioskId = kioskId;
return instance; return instance;
} }
@ -136,7 +134,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
.getDefaultSharedPreferences(activity) .getDefaultSharedPreferences(activity)
.getString(getString(R.string.content_country_key), .getString(getString(R.string.content_country_key),
getString(R.string.default_country_value)); getString(R.string.default_country_value));
return ExtractorHelper.getKioskInfo(serviceId, url, contentCountry, forceReload); return ExtractorHelper.getKioskInfo(serviceId,
url,
contentCountry,
forceReload);
} }
@Override @Override
@ -145,7 +146,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
.getDefaultSharedPreferences(activity) .getDefaultSharedPreferences(activity)
.getString(getString(R.string.content_country_key), .getString(getString(R.string.content_country_key),
getString(R.string.default_country_value)); getString(R.string.default_country_value));
return ExtractorHelper.getMoreKioskItems(serviceId, url, currentNextPageUrl, contentCountry); return ExtractorHelper.getMoreKioskItems(serviceId,
url,
currentNextPageUrl,
contentCountry);
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////

View File

@ -6,6 +6,7 @@ import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -19,6 +20,7 @@ import android.widget.TextView;
import org.reactivestreams.Subscriber; import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription; import org.reactivestreams.Subscription;
import org.schabi.newpipe.App;
import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
@ -28,12 +30,14 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment; import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
import org.schabi.newpipe.info_list.InfoItemDialog; import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.local.playlist.RemotePlaylistManager; import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue; import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.ImageDisplayConstants;
@ -267,11 +271,16 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
if (!TextUtils.isEmpty(result.getUploaderName())) { if (!TextUtils.isEmpty(result.getUploaderName())) {
headerUploaderName.setText(result.getUploaderName()); headerUploaderName.setText(result.getUploaderName());
if (!TextUtils.isEmpty(result.getUploaderUrl())) { if (!TextUtils.isEmpty(result.getUploaderUrl())) {
headerUploaderLayout.setOnClickListener(v -> headerUploaderLayout.setOnClickListener(v -> {
try {
NavigationHelper.openChannelFragment(getFragmentManager(), NavigationHelper.openChannelFragment(getFragmentManager(),
result.getServiceId(), result.getUploaderUrl(), result.getServiceId(),
result.getUploaderName()) result.getUploaderUrl(),
); result.getUploaderName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
});
} }
} }
@ -339,7 +348,11 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
if (super.onError(exception)) return true; if (super.onError(exception)) return true;
int errorId = exception instanceof ExtractionException ? R.string.parsing_error : R.string.general_error; int errorId = exception instanceof ExtractionException ? R.string.parsing_error : R.string.general_error;
onUnrecoverableError(exception, UserAction.REQUESTED_PLAYLIST, NewPipe.getNameOfService(serviceId), url, errorId); onUnrecoverableError(exception,
UserAction.REQUESTED_PLAYLIST,
NewPipe.getNameOfService(serviceId),
url,
errorId);
return true; return true;
} }

View File

@ -29,6 +29,8 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import com.facebook.stetho.common.ListUtil;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.ReCaptchaActivity; import org.schabi.newpipe.ReCaptchaActivity;
import org.schabi.newpipe.database.history.model.SearchHistoryEntry; import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
@ -37,26 +39,28 @@ import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.search.SearchEngine; import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.search.SearchResult; import org.schabi.newpipe.extractor.search.SearchInfo;
import org.schabi.newpipe.fragments.BackPressable; import org.schabi.newpipe.fragments.BackPressable;
import org.schabi.newpipe.fragments.list.BaseListFragment; import org.schabi.newpipe.fragments.list.BaseListFragment;
import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.AnimationUtils; import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.LayoutManagerSmoothScroller; import org.schabi.newpipe.util.LayoutManagerSmoothScroller;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ServiceHelper;
import java.io.IOException; import java.io.IOException;
import java.io.InterruptedIOException; import java.io.InterruptedIOException;
import java.net.SocketException; import java.net.SocketException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import icepick.State; import icepick.State;
@ -65,14 +69,15 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject; import io.reactivex.subjects.PublishSubject;
import static java.util.Arrays.asList;
import static org.schabi.newpipe.util.AnimationUtils.animateView; import static org.schabi.newpipe.util.AnimationUtils.animateView;
public class SearchFragment public class SearchFragment
extends BaseListFragment<SearchResult, ListExtractor.InfoItemsPage> extends BaseListFragment<SearchInfo, ListExtractor.InfoItemsPage>
implements BackPressable { implements BackPressable {
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
@ -92,19 +97,28 @@ public class SearchFragment
@State @State
protected int filterItemCheckedId = -1; protected int filterItemCheckedId = -1;
private SearchEngine.Filter filter = SearchEngine.Filter.ANY;
@State @State
protected int serviceId = Constants.NO_SERVICE_ID; protected int serviceId = Constants.NO_SERVICE_ID;
// this three represet the current search query
@State @State
protected String searchQuery; protected String searchString;
@State @State
protected String lastSearchedQuery; protected String[] contentFilter;
@State
protected String sortFilter;
// these represtent the last search
@State
protected String lastSearchedString;
@State @State
protected boolean wasSearchFocused = false; protected boolean wasSearchFocused = false;
private int currentPage = 0; private StreamingService service;
private int currentNextPage = 0; private String currentPageUrl;
private String nextPageUrl;
private String contentCountry; private String contentCountry;
private boolean isSuggestionsEnabled = true; private boolean isSuggestionsEnabled = true;
private boolean isSearchHistoryEnabled = true; private boolean isSearchHistoryEnabled = true;
@ -130,11 +144,11 @@ public class SearchFragment
/*////////////////////////////////////////////////////////////////////////*/ /*////////////////////////////////////////////////////////////////////////*/
public static SearchFragment getInstance(int serviceId, String query) { public static SearchFragment getInstance(int serviceId, String searchString) {
SearchFragment searchFragment = new SearchFragment(); SearchFragment searchFragment = new SearchFragment();
searchFragment.setQuery(serviceId, query); searchFragment.setQuery(serviceId, searchString, new String[0], "");
if (!TextUtils.isEmpty(query)) { if (!TextUtils.isEmpty(searchString)) {
searchFragment.setSearchOnResume(); searchFragment.setSearchOnResume();
} }
@ -202,13 +216,22 @@ public class SearchFragment
if (DEBUG) Log.d(TAG, "onResume() called"); if (DEBUG) Log.d(TAG, "onResume() called");
super.onResume(); super.onResume();
if (!TextUtils.isEmpty(searchQuery)) { try {
service = NewPipe.getService(serviceId);
} catch (Exception e) {
ErrorActivity.reportError(getActivity(), e, getActivity().getClass(),
getActivity().findViewById(android.R.id.content),
ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
"",
"", R.string.general_error));
}
if (!TextUtils.isEmpty(searchString)) {
if (wasLoading.getAndSet(false)) { if (wasLoading.getAndSet(false)) {
if (currentNextPage > currentPage) loadMoreItems(); search(searchString, contentFilter, sortFilter);
else search(searchQuery);
} else if (infoListAdapter.getItemsList().size() == 0) { } else if (infoListAdapter.getItemsList().size() == 0) {
if (savedState == null) { if (savedState == null) {
search(searchQuery); search(searchString, contentFilter, sortFilter);
} else if (!isLoading.get() && !wasSearchFocused) { } else if (!isLoading.get() && !wasSearchFocused) {
infoListAdapter.clearStreamItemList(); infoListAdapter.clearStreamItemList();
showEmptyState(); showEmptyState();
@ -218,7 +241,7 @@ public class SearchFragment
if (suggestionDisposable == null || suggestionDisposable.isDisposed()) initSuggestionObserver(); if (suggestionDisposable == null || suggestionDisposable.isDisposed()) initSuggestionObserver();
if (TextUtils.isEmpty(searchQuery) || wasSearchFocused) { if (TextUtils.isEmpty(searchString) || wasSearchFocused) {
showKeyboardSearch(); showKeyboardSearch();
showSuggestionsPanel(); showSuggestionsPanel();
} else { } else {
@ -247,8 +270,9 @@ public class SearchFragment
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case ReCaptchaActivity.RECAPTCHA_REQUEST: case ReCaptchaActivity.RECAPTCHA_REQUEST:
if (resultCode == Activity.RESULT_OK && !TextUtils.isEmpty(searchQuery)) { if (resultCode == Activity.RESULT_OK
search(searchQuery); && !TextUtils.isEmpty(searchString)) {
search(searchString, contentFilter, sortFilter);
} else Log.e(TAG, "ReCaptcha failed"); } else Log.e(TAG, "ReCaptcha failed");
break; break;
@ -282,20 +306,22 @@ public class SearchFragment
@Override @Override
public void writeTo(Queue<Object> objectsToSave) { public void writeTo(Queue<Object> objectsToSave) {
super.writeTo(objectsToSave); super.writeTo(objectsToSave);
objectsToSave.add(currentPage); objectsToSave.add(currentPageUrl);
objectsToSave.add(currentNextPage); objectsToSave.add(nextPageUrl);
} }
@Override @Override
public void readFrom(@NonNull Queue<Object> savedObjects) throws Exception { public void readFrom(@NonNull Queue<Object> savedObjects) throws Exception {
super.readFrom(savedObjects); super.readFrom(savedObjects);
currentPage = (int) savedObjects.poll(); currentPageUrl = (String) savedObjects.poll();
currentNextPage = (int) savedObjects.poll(); nextPageUrl = (String) savedObjects.poll();
} }
@Override @Override
public void onSaveInstanceState(Bundle bundle) { public void onSaveInstanceState(Bundle bundle) {
searchQuery = searchEditText != null ? searchEditText.getText().toString() : searchQuery; searchString = searchEditText != null
? searchEditText.getText().toString()
: searchString;
super.onSaveInstanceState(bundle); super.onSaveInstanceState(bundle);
} }
@ -305,8 +331,11 @@ public class SearchFragment
@Override @Override
public void reloadContent() { public void reloadContent() {
if (!TextUtils.isEmpty(searchQuery) || (searchEditText != null && !TextUtils.isEmpty(searchEditText.getText()))) { if (!TextUtils.isEmpty(searchString)
search(!TextUtils.isEmpty(searchQuery) ? searchQuery : searchEditText.getText().toString()); || (searchEditText != null && !TextUtils.isEmpty(searchEditText.getText()))) {
search(!TextUtils.isEmpty(searchString)
? searchString
: searchEditText.getText().toString(), new String[0], "");
} else { } else {
if (searchEditText != null) { if (searchEditText != null) {
searchEditText.setText(""); searchEditText.setText("");
@ -330,22 +359,32 @@ public class SearchFragment
supportActionBar.setDisplayHomeAsUpEnabled(true); supportActionBar.setDisplayHomeAsUpEnabled(true);
} }
inflater.inflate(R.menu.menu_search, menu); int itemId = 0;
boolean isFirstItem = true;
final Context c = getContext();
for(String filter : service.getSearchQIHFactory().getAvailableContentFilter()) {
MenuItem item = menu.add(1,
itemId++,
0,
ServiceHelper.getTranslatedFilterString(filter, c));
if(isFirstItem) {
item.setChecked(true);
isFirstItem = false;
}
}
menu.setGroupCheckable(1, true, true);
restoreFilterChecked(menu, filterItemCheckedId); restoreFilterChecked(menu, filterItemCheckedId);
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_filter_all: List<String> contentFilter = new ArrayList<>(1);
case R.id.menu_filter_video: contentFilter.add(item.getTitle().toString());
case R.id.menu_filter_channel: changeContentFilter(item, contentFilter);
case R.id.menu_filter_playlist:
changeFilter(item, getFilterFromMenuId(item.getItemId())); return true;
return true;
default:
return super.onOptionsItemSelected(item);
}
} }
private void restoreFilterChecked(Menu menu, int itemId) { private void restoreFilterChecked(Menu menu, int itemId) {
@ -354,21 +393,6 @@ public class SearchFragment
if (item == null) return; if (item == null) return;
item.setChecked(true); item.setChecked(true);
filter = getFilterFromMenuId(itemId);
}
}
private SearchEngine.Filter getFilterFromMenuId(int itemId) {
switch (itemId) {
case R.id.menu_filter_video:
return SearchEngine.Filter.STREAM;
case R.id.menu_filter_channel:
return SearchEngine.Filter.CHANNEL;
case R.id.menu_filter_playlist:
return SearchEngine.Filter.PLAYLIST;
case R.id.menu_filter_all:
default:
return SearchEngine.Filter.ANY;
} }
} }
@ -379,14 +403,21 @@ public class SearchFragment
private TextWatcher textWatcher; private TextWatcher textWatcher;
private void showSearchOnStart() { private void showSearchOnStart() {
if (DEBUG) Log.d(TAG, "showSearchOnStart() called, searchQuery → " + searchQuery+", lastSearchedQuery → " + lastSearchedQuery); if (DEBUG) Log.d(TAG, "showSearchOnStart() called, searchQuery → "
searchEditText.setText(searchQuery); + searchString
+ ", lastSearchedQuery → "
+ lastSearchedString);
searchEditText.setText(searchString);
if (TextUtils.isEmpty(searchQuery) || TextUtils.isEmpty(searchEditText.getText())) { if (TextUtils.isEmpty(searchString) || TextUtils.isEmpty(searchEditText.getText())) {
searchToolbarContainer.setTranslationX(100); searchToolbarContainer.setTranslationX(100);
searchToolbarContainer.setAlpha(0f); searchToolbarContainer.setAlpha(0f);
searchToolbarContainer.setVisibility(View.VISIBLE); searchToolbarContainer.setVisibility(View.VISIBLE);
searchToolbarContainer.animate().translationX(0).alpha(1f).setDuration(200).setInterpolator(new DecelerateInterpolator()).start(); searchToolbarContainer.animate()
.translationX(0)
.alpha(1f)
.setDuration(200)
.setInterpolator(new DecelerateInterpolator()).start();
} else { } else {
searchToolbarContainer.setTranslationX(0); searchToolbarContainer.setTranslationX(0);
searchToolbarContainer.setAlpha(1f); searchToolbarContainer.setAlpha(1f);
@ -396,47 +427,38 @@ public class SearchFragment
private void initSearchListeners() { private void initSearchListeners() {
if (DEBUG) Log.d(TAG, "initSearchListeners() called"); if (DEBUG) Log.d(TAG, "initSearchListeners() called");
searchClear.setOnClickListener(new View.OnClickListener() { searchClear.setOnClickListener(v -> {
@Override if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]");
public void onClick(View v) { if (TextUtils.isEmpty(searchEditText.getText())) {
if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]"); NavigationHelper.gotoMainFragment(getFragmentManager());
if (TextUtils.isEmpty(searchEditText.getText())) { return;
NavigationHelper.gotoMainFragment(getFragmentManager());
return;
}
searchEditText.setText("");
suggestionListAdapter.setItems(new ArrayList<SuggestionItem>());
showKeyboardSearch();
} }
searchEditText.setText("");
suggestionListAdapter.setItems(new ArrayList<>());
showKeyboardSearch();
}); });
TooltipCompat.setTooltipText(searchClear, getString(R.string.clear)); TooltipCompat.setTooltipText(searchClear, getString(R.string.clear));
searchEditText.setOnClickListener(new View.OnClickListener() { searchEditText.setOnClickListener(v -> {
@Override if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]");
public void onClick(View v) { if (isSuggestionsEnabled && errorPanelRoot.getVisibility() != View.VISIBLE) {
if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]"); showSuggestionsPanel();
if (isSuggestionsEnabled && errorPanelRoot.getVisibility() != View.VISIBLE) {
showSuggestionsPanel();
}
} }
}); });
searchEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() { searchEditText.setOnFocusChangeListener((View v, boolean hasFocus) -> {
@Override if (DEBUG) Log.d(TAG, "onFocusChange() called with: v = [" + v + "], hasFocus = [" + hasFocus + "]");
public void onFocusChange(View v, boolean hasFocus) { if (isSuggestionsEnabled && hasFocus && errorPanelRoot.getVisibility() != View.VISIBLE) {
if (DEBUG) Log.d(TAG, "onFocusChange() called with: v = [" + v + "], hasFocus = [" + hasFocus + "]"); showSuggestionsPanel();
if (isSuggestionsEnabled && hasFocus && errorPanelRoot.getVisibility() != View.VISIBLE) {
showSuggestionsPanel();
}
} }
}); });
suggestionListAdapter.setListener(new SuggestionListAdapter.OnSuggestionItemSelected() { suggestionListAdapter.setListener(new SuggestionListAdapter.OnSuggestionItemSelected() {
@Override @Override
public void onSuggestionItemSelected(SuggestionItem item) { public void onSuggestionItemSelected(SuggestionItem item) {
search(item.query); search(item.query, new String[0], "");
searchEditText.setText(item.query); searchEditText.setText(item.query);
} }
@ -469,21 +491,22 @@ public class SearchFragment
} }
}; };
searchEditText.addTextChangedListener(textWatcher); searchEditText.addTextChangedListener(textWatcher);
searchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { searchEditText.setOnEditorActionListener(
@Override (TextView v, int actionId, KeyEvent event) -> {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (DEBUG) {
if (DEBUG) { Log.d(TAG, "onEditorAction() called with: v = [" + v + "], actionId = [" + actionId + "], event = [" + event + "]");
Log.d(TAG, "onEditorAction() called with: v = [" + v + "], actionId = [" + actionId + "], event = [" + event + "]"); }
} if (event != null
if (event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER || event.getAction() == EditorInfo.IME_ACTION_SEARCH)) { && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER
search(searchEditText.getText().toString()); || event.getAction() == EditorInfo.IME_ACTION_SEARCH)) {
return true; search(searchEditText.getText().toString(), new String[0], "");
} return true;
return false; }
} return false;
}); });
if (suggestionDisposable == null || suggestionDisposable.isDisposed()) initSuggestionObserver(); if (suggestionDisposable == null || suggestionDisposable.isDisposed())
initSuggestionObserver();
} }
private void unsetSearchListeners() { private void unsetSearchListeners() {
@ -513,7 +536,8 @@ public class SearchFragment
if (searchEditText == null) return; if (searchEditText == null) return;
if (searchEditText.requestFocus()) { if (searchEditText.requestFocus()) {
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) activity.getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(searchEditText, InputMethodManager.SHOW_IMPLICIT); imm.showSoftInput(searchEditText, InputMethodManager.SHOW_IMPLICIT);
} }
} }
@ -522,8 +546,10 @@ public class SearchFragment
if (DEBUG) Log.d(TAG, "hideKeyboardSearch() called"); if (DEBUG) Log.d(TAG, "hideKeyboardSearch() called");
if (searchEditText == null) return; if (searchEditText == null) return;
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) activity.getSystemService(
imm.hideSoftInputFromWindow(searchEditText.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(searchEditText.getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
searchEditText.clearFocus(); searchEditText.clearFocus();
} }
@ -554,10 +580,12 @@ public class SearchFragment
@Override @Override
public boolean onBackPressed() { public boolean onBackPressed() {
if (suggestionsPanel.getVisibility() == View.VISIBLE && infoListAdapter.getItemsList().size() > 0 && !isLoading.get()) { if (suggestionsPanel.getVisibility() == View.VISIBLE
&& infoListAdapter.getItemsList().size() > 0
&& !isLoading.get()) {
hideSuggestionsPanel(); hideSuggestionsPanel();
hideKeyboardSearch(); hideKeyboardSearch();
searchEditText.setText(lastSearchedQuery); searchEditText.setText(lastSearchedString);
return true; return true;
} }
return false; return false;
@ -573,8 +601,10 @@ public class SearchFragment
final Observable<String> observable = suggestionPublisher final Observable<String> observable = suggestionPublisher
.debounce(SUGGESTIONS_DEBOUNCE, TimeUnit.MILLISECONDS) .debounce(SUGGESTIONS_DEBOUNCE, TimeUnit.MILLISECONDS)
.startWith(searchQuery != null ? searchQuery : "") .startWith(searchString != null
.filter(query -> isSuggestionsEnabled); ? searchString
: "")
.filter(searchString -> isSuggestionsEnabled);
suggestionDisposable = observable suggestionDisposable = observable
.switchMap(query -> { .switchMap(query -> {
@ -645,56 +675,44 @@ public class SearchFragment
// no-op // no-op
} }
private void search(final String query) { private void search(final String searchString, String[] contentFilter, String sortFilter) {
if (DEBUG) Log.d(TAG, "search() called with: query = [" + query + "]"); if (DEBUG) Log.d(TAG, "search() called with: query = [" + searchString + "]");
if (query.isEmpty()) return; if (searchString.isEmpty()) return;
try { try {
final StreamingService service = NewPipe.getServiceByUrl(query); final StreamingService service = NewPipe.getServiceByUrl(searchString);
if (service != null) { if (service != null) {
showLoading(); showLoading();
disposables.add(Observable disposables.add(Observable
.fromCallable(new Callable<Intent>() { .fromCallable(() ->
@Override NavigationHelper.getIntentByLink(activity, service, searchString))
public Intent call() throws Exception {
return NavigationHelper.getIntentByLink(activity, service, query);
}
})
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Intent>() { .subscribe(intent -> {
@Override getFragmentManager().popBackStackImmediate();
public void accept(Intent intent) throws Exception { activity.startActivity(intent);
getFragmentManager().popBackStackImmediate(); }, throwable ->
activity.startActivity(intent); showError(getString(R.string.url_not_supported_toast), false)));
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
showError(getString(R.string.url_not_supported_toast), false);
}
}));
return; return;
} }
} catch (Exception e) { } catch (Exception e) {
// Exception occurred, it's not a url // Exception occurred, it's not a url
} }
lastSearchedQuery = query; lastSearchedString = this.searchString;
searchQuery = query; this.searchString = searchString;
currentPage = 0;
infoListAdapter.clearStreamItemList(); infoListAdapter.clearStreamItemList();
hideSuggestionsPanel(); hideSuggestionsPanel();
hideKeyboardSearch(); hideKeyboardSearch();
historyRecordManager.onSearched(serviceId, query) historyRecordManager.onSearched(serviceId, searchString)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe( .subscribe(
ignored -> {}, ignored -> {},
error -> showSnackBarError(error, UserAction.SEARCHED, error -> showSnackBarError(error, UserAction.SEARCHED,
NewPipe.getNameOfService(serviceId), query, 0) NewPipe.getNameOfService(serviceId), searchString, 0)
); );
suggestionPublisher.onNext(query); suggestionPublisher.onNext(searchString);
startLoading(false); startLoading(false);
} }
@ -703,11 +721,16 @@ public class SearchFragment
super.startLoading(forceLoad); super.startLoading(forceLoad);
if (disposables != null) disposables.clear(); if (disposables != null) disposables.clear();
if (searchDisposable != null) searchDisposable.dispose(); if (searchDisposable != null) searchDisposable.dispose();
searchDisposable = ExtractorHelper.searchFor(serviceId, searchQuery, currentPage, contentCountry, filter) searchDisposable = ExtractorHelper.searchFor(serviceId,
searchString,
Arrays.asList(contentFilter),
sortFilter,
contentCountry)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.doOnEvent((searchResult, throwable) -> isLoading.set(false)) .doOnEvent((searchResult, throwable) -> isLoading.set(false))
.subscribe(this::handleResult, this::onError); .subscribe(this::handleResult, this::onError);
} }
@Override @Override
@ -715,8 +738,13 @@ public class SearchFragment
isLoading.set(true); isLoading.set(true);
showListFooter(true); showListFooter(true);
if (searchDisposable != null) searchDisposable.dispose(); if (searchDisposable != null) searchDisposable.dispose();
currentNextPage = currentPage + 1; searchDisposable = ExtractorHelper.getMoreSearchItems(
searchDisposable = ExtractorHelper.getMoreSearchItems(serviceId, searchQuery, currentNextPage, contentCountry, filter) serviceId,
searchString,
asList(contentFilter),
sortFilter,
nextPageUrl,
contentCountry)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.doOnEvent((nextItemsResult, throwable) -> isLoading.set(false)) .doOnEvent((nextItemsResult, throwable) -> isLoading.set(false))
@ -739,19 +767,22 @@ public class SearchFragment
// Utils // Utils
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private void changeFilter(MenuItem item, SearchEngine.Filter filter) { private void changeContentFilter(MenuItem item, List<String> contentFilter) {
this.filter = filter;
this.filterItemCheckedId = item.getItemId(); this.filterItemCheckedId = item.getItemId();
item.setChecked(true); item.setChecked(true);
if (!TextUtils.isEmpty(searchQuery)) { this.contentFilter = new String[] {contentFilter.get(0)};
search(searchQuery);
if (!TextUtils.isEmpty(searchString)) {
search(searchString, this.contentFilter, sortFilter);
} }
} }
private void setQuery(int serviceId, String searchQuery) { private void setQuery(int serviceId, String searchString, String[] contentfilter, String sortFilter) {
this.serviceId = serviceId; this.serviceId = serviceId;
this.searchQuery = searchQuery; this.searchString = searchString;
this.contentFilter = contentfilter;
this.sortFilter = sortFilter;
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
@ -772,8 +803,11 @@ public class SearchFragment
if (DEBUG) Log.d(TAG, "onSuggestionError() called with: exception = [" + exception + "]"); if (DEBUG) Log.d(TAG, "onSuggestionError() called with: exception = [" + exception + "]");
if (super.onError(exception)) return; if (super.onError(exception)) return;
int errorId = exception instanceof ParsingException ? R.string.parsing_error : R.string.general_error; int errorId = exception instanceof ParsingException
onUnrecoverableError(exception, UserAction.GET_SUGGESTIONS, NewPipe.getNameOfService(serviceId), searchQuery, errorId); ? R.string.parsing_error
: R.string.general_error;
onUnrecoverableError(exception, UserAction.GET_SUGGESTIONS,
NewPipe.getNameOfService(serviceId), searchString, errorId);
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
@ -798,16 +832,19 @@ public class SearchFragment
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@Override @Override
public void handleResult(@NonNull SearchResult result) { public void handleResult(@NonNull SearchInfo result) {
if (!result.errors.isEmpty()) { if (!result.getErrors().isEmpty()) {
showSnackBarError(result.errors, UserAction.SEARCHED, NewPipe.getNameOfService(serviceId), searchQuery, 0); showSnackBarError(result.getErrors(), UserAction.SEARCHED,
NewPipe.getNameOfService(serviceId), searchString, 0);
} }
lastSearchedQuery = searchQuery; lastSearchedString = searchString;
nextPageUrl = result.getNextPageUrl();
currentPageUrl = result.getUrl();
if (infoListAdapter.getItemsList().size() == 0) { if (infoListAdapter.getItemsList().size() == 0) {
if (!result.getResults().isEmpty()) { if (!result.getRelatedItems().isEmpty()) {
infoListAdapter.addInfoItemList(result.getResults()); infoListAdapter.addInfoItemList(result.getRelatedItems());
} else { } else {
infoListAdapter.clearStreamItemList(); infoListAdapter.clearStreamItemList();
showEmptyState(); showEmptyState();
@ -821,12 +858,13 @@ public class SearchFragment
@Override @Override
public void handleNextItems(ListExtractor.InfoItemsPage result) { public void handleNextItems(ListExtractor.InfoItemsPage result) {
showListFooter(false); showListFooter(false);
currentPage = Integer.parseInt(result.getNextPageUrl()); currentPageUrl = result.getNextPageUrl();
infoListAdapter.addInfoItemList(result.getItems()); infoListAdapter.addInfoItemList(result.getItems());
if (!result.getErrors().isEmpty()) { if (!result.getErrors().isEmpty()) {
showSnackBarError(result.getErrors(), UserAction.SEARCHED, NewPipe.getNameOfService(serviceId) showSnackBarError(result.getErrors(), UserAction.SEARCHED,
, "\"" + searchQuery + "\" → page " + currentPage, 0); NewPipe.getNameOfService(serviceId)
, "\"" + searchString + "\" → page: " + nextPageUrl, 0);
} }
super.handleNextItems(result); super.handleNextItems(result);
} }
@ -835,12 +873,15 @@ public class SearchFragment
protected boolean onError(Throwable exception) { protected boolean onError(Throwable exception) {
if (super.onError(exception)) return true; if (super.onError(exception)) return true;
if (exception instanceof SearchEngine.NothingFoundException) { if (exception instanceof SearchExtractor.NothingFoundException) {
infoListAdapter.clearStreamItemList(); infoListAdapter.clearStreamItemList();
showEmptyState(); showEmptyState();
} else { } else {
int errorId = exception instanceof ParsingException ? R.string.parsing_error : R.string.general_error; int errorId = exception instanceof ParsingException
onUnrecoverableError(exception, UserAction.SEARCHED, NewPipe.getNameOfService(serviceId), searchQuery, errorId); ? R.string.parsing_error
: R.string.general_error;
onUnrecoverableError(exception, UserAction.SEARCHED,
NewPipe.getNameOfService(serviceId), searchString, errorId);
} }
return true; return true;

View File

@ -6,6 +6,7 @@ import android.os.Parcelable;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -19,9 +20,11 @@ import org.schabi.newpipe.database.LocalItem;
import org.schabi.newpipe.database.playlist.PlaylistLocalItem; import org.schabi.newpipe.database.playlist.PlaylistLocalItem;
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.local.BaseLocalListFragment; import org.schabi.newpipe.local.BaseLocalListFragment;
import org.schabi.newpipe.local.playlist.LocalPlaylistManager; import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
import org.schabi.newpipe.local.playlist.RemotePlaylistManager; import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture; import org.schabi.newpipe.util.OnClickGesture;
@ -99,19 +102,26 @@ public final class BookmarkFragment
itemListAdapter.setSelectedListener(new OnClickGesture<LocalItem>() { itemListAdapter.setSelectedListener(new OnClickGesture<LocalItem>() {
@Override @Override
public void selected(LocalItem selectedItem) { public void selected(LocalItem selectedItem) {
// Requires the parent fragment to find holder for fragment replacement try {
if (getParentFragment() == null) return; // Requires the parent fragment to find holder for fragment replacement
final FragmentManager fragmentManager = getParentFragment().getFragmentManager(); if (getParentFragment() == null) return;
final FragmentManager fragmentManager = getParentFragment().getFragmentManager();
if (selectedItem instanceof PlaylistMetadataEntry) { if (selectedItem instanceof PlaylistMetadataEntry) {
final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem); final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem);
NavigationHelper.openLocalPlaylistFragment(fragmentManager, entry.uid, NavigationHelper.openLocalPlaylistFragment(fragmentManager, entry.uid,
entry.name); entry.name);
} else if (selectedItem instanceof PlaylistRemoteEntity) { } else if (selectedItem instanceof PlaylistRemoteEntity) {
final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem); final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem);
NavigationHelper.openPlaylistFragment(fragmentManager, entry.getServiceId(), NavigationHelper.openPlaylistFragment(
entry.getUrl(), entry.getName()); fragmentManager,
entry.getServiceId(),
entry.getUrl(),
entry.getName());
}
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
} }
} }

View File

@ -15,6 +15,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -38,6 +39,7 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
import org.schabi.newpipe.fragments.BaseStateFragment; import org.schabi.newpipe.fragments.BaseStateFragment;
import org.schabi.newpipe.info_list.InfoListAdapter; import org.schabi.newpipe.info_list.InfoListAdapter;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService; import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService;
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService; import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService;
@ -318,9 +320,15 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt
infoListAdapter.setOnChannelSelectedListener(new OnClickGesture<ChannelInfoItem>() { infoListAdapter.setOnChannelSelectedListener(new OnClickGesture<ChannelInfoItem>() {
@Override @Override
public void selected(ChannelInfoItem selectedItem) { public void selected(ChannelInfoItem selectedItem) {
// Requires the parent fragment to find holder for fragment replacement try {
NavigationHelper.openChannelFragment(getParentFragment().getFragmentManager(), // Requires the parent fragment to find holder for fragment replacement
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName()); NavigationHelper.openChannelFragment(getParentFragment().getFragmentManager(),
selectedItem.getServiceId(),
selectedItem.getUrl(),
selectedItem.getName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
} }
}); });

View File

@ -6,7 +6,7 @@ public class Constants {
public static final String KEY_TITLE = "key_title"; public static final String KEY_TITLE = "key_title";
public static final String KEY_LINK_TYPE = "key_link_type"; public static final String KEY_LINK_TYPE = "key_link_type";
public static final String KEY_OPEN_SEARCH = "key_open_search"; public static final String KEY_OPEN_SEARCH = "key_open_search";
public static final String KEY_QUERY = "key_query"; public static final String KEY_SEARCH_STRING = "key_search_string";
public static final String KEY_THEME_CHANGE = "key_theme_change"; public static final String KEY_THEME_CHANGE = "key_theme_change";
public static final String KEY_MAIN_PAGE_CHANGE = "key_main_page_change"; public static final String KEY_MAIN_PAGE_CHANGE = "key_main_page_change";

View File

@ -37,9 +37,8 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.extractor.kiosk.KioskInfo; import org.schabi.newpipe.extractor.kiosk.KioskInfo;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.search.SearchEngine; import org.schabi.newpipe.extractor.search.SearchInfo;
import org.schabi.newpipe.extractor.search.SearchResult; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.report.UserAction;
@ -50,7 +49,6 @@ import java.util.List;
import io.reactivex.Maybe; import io.reactivex.Maybe;
import io.reactivex.Single; import io.reactivex.Single;
import io.reactivex.annotations.NonNull;
public final class ExtractorHelper { public final class ExtractorHelper {
private static final String TAG = ExtractorHelper.class.getSimpleName(); private static final String TAG = ExtractorHelper.class.getSimpleName();
@ -66,29 +64,35 @@ public final class ExtractorHelper {
} }
} }
public static Single<SearchResult> searchFor(final int serviceId, public static Single<SearchInfo> searchFor(final int serviceId,
final String query, final String searchString,
final int pageNumber, final List<String> contentFilter,
final String contentCountry, final String sortFilter,
final SearchEngine.Filter filter) { final String contentCountry) {
checkServiceId(serviceId); checkServiceId(serviceId);
return Single.fromCallable(() -> return Single.fromCallable(() ->
SearchResult.getSearchResult(NewPipe.getService(serviceId).getSearchEngine(), SearchInfo.getInfo(NewPipe.getService(serviceId),
query, pageNumber, contentCountry, filter) NewPipe.getService(serviceId)
); .getSearchQIHFactory()
.fromQuery(searchString, contentFilter, sortFilter),
contentCountry));
} }
public static Single<InfoItemsPage> getMoreSearchItems(final int serviceId, public static Single<InfoItemsPage> getMoreSearchItems(final int serviceId,
final String query, final String searchString,
final int nextPageNumber, final List<String> contentFilter,
final String searchLanguage, final String sortFilter,
final SearchEngine.Filter filter) { final String pageUrl,
final String contentCountry) {
checkServiceId(serviceId); checkServiceId(serviceId);
return searchFor(serviceId, query, nextPageNumber, searchLanguage, filter) return Single.fromCallable(() ->
.map((@NonNull SearchResult searchResult) -> SearchInfo.getMoreItems(NewPipe.getService(serviceId),
new InfoItemsPage(searchResult.resultList, NewPipe.getService(serviceId)
nextPageNumber + "", .getSearchQIHFactory()
searchResult.errors)); .fromQuery(searchString, contentFilter, sortFilter),
contentCountry,
pageUrl));
} }
public static Single<List<String>> suggestionsFor(final int serviceId, public static Single<List<String>> suggestionsFor(final int serviceId,
@ -233,7 +237,6 @@ public final class ExtractorHelper {
serviceId == -1 ? "none" : NewPipe.getNameOfService(serviceId), url + (optionalErrorMessage == null ? "" : optionalErrorMessage), errorId)); serviceId == -1 ? "none" : NewPipe.getNameOfService(serviceId), url + (optionalErrorMessage == null ? "" : optionalErrorMessage), errorId));
} }
}); });
} }
/** /**

View File

@ -26,10 +26,13 @@ import org.schabi.newpipe.download.DownloadActivity;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.stream.AudioStream; import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.Stream; import org.schabi.newpipe.extractor.stream.Stream;
import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
import org.schabi.newpipe.fragments.MainFragment; import org.schabi.newpipe.fragments.MainFragment;
import org.schabi.newpipe.fragments.detail.VideoDetailFragment; import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
import org.schabi.newpipe.fragments.list.channel.ChannelFragment; import org.schabi.newpipe.fragments.list.channel.ChannelFragment;
@ -283,9 +286,11 @@ public class NavigationHelper {
return fragmentManager.popBackStackImmediate(SEARCH_FRAGMENT_TAG, 0); return fragmentManager.popBackStackImmediate(SEARCH_FRAGMENT_TAG, 0);
} }
public static void openSearchFragment(FragmentManager fragmentManager, int serviceId, String query) { public static void openSearchFragment(FragmentManager fragmentManager,
int serviceId,
String searchString) {
defaultTransaction(fragmentManager) defaultTransaction(fragmentManager)
.replace(R.id.fragment_holder, SearchFragment.getInstance(serviceId, query)) .replace(R.id.fragment_holder, SearchFragment.getInstance(serviceId, searchString))
.addToBackStack(SEARCH_FRAGMENT_TAG) .addToBackStack(SEARCH_FRAGMENT_TAG)
.commit(); .commit();
} }
@ -314,7 +319,11 @@ public class NavigationHelper {
.commit(); .commit();
} }
public static void openChannelFragment(FragmentManager fragmentManager, int serviceId, String url, String name) { public static void openChannelFragment(
FragmentManager fragmentManager,
int serviceId,
String url,
String name) {
if (name == null) name = ""; if (name == null) name = "";
defaultTransaction(fragmentManager) defaultTransaction(fragmentManager)
.replace(R.id.fragment_holder, ChannelFragment.getInstance(serviceId, url, name)) .replace(R.id.fragment_holder, ChannelFragment.getInstance(serviceId, url, name))
@ -322,7 +331,10 @@ public class NavigationHelper {
.commit(); .commit();
} }
public static void openPlaylistFragment(FragmentManager fragmentManager, int serviceId, String url, String name) { public static void openPlaylistFragment(FragmentManager fragmentManager,
int serviceId,
String url,
String name) {
if (name == null) name = ""; if (name == null) name = "";
defaultTransaction(fragmentManager) defaultTransaction(fragmentManager)
.replace(R.id.fragment_holder, PlaylistFragment.getInstance(serviceId, url, name)) .replace(R.id.fragment_holder, PlaylistFragment.getInstance(serviceId, url, name))
@ -370,10 +382,10 @@ public class NavigationHelper {
// Through Intents // Through Intents
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
public static void openSearch(Context context, int serviceId, String query) { public static void openSearch(Context context, int serviceId, String searchString) {
Intent mIntent = new Intent(context, MainActivity.class); Intent mIntent = new Intent(context, MainActivity.class);
mIntent.putExtra(Constants.KEY_SERVICE_ID, serviceId); mIntent.putExtra(Constants.KEY_SERVICE_ID, serviceId);
mIntent.putExtra(Constants.KEY_QUERY, query); mIntent.putExtra(Constants.KEY_SEARCH_STRING, searchString);
mIntent.putExtra(Constants.KEY_OPEN_SEARCH, true); mIntent.putExtra(Constants.KEY_OPEN_SEARCH, true);
context.startActivity(mIntent); context.startActivity(mIntent);
} }
@ -467,7 +479,8 @@ public class NavigationHelper {
switch (linkType) { switch (linkType) {
case STREAM: case STREAM:
rIntent.putExtra(VideoDetailFragment.AUTO_PLAY, PreferenceManager.getDefaultSharedPreferences(context) rIntent.putExtra(VideoDetailFragment.AUTO_PLAY,
PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(context.getString(R.string.autoplay_through_intent_key), false)); .getBoolean(context.getString(R.string.autoplay_through_intent_key), false));
break; break;
} }

View File

@ -5,7 +5,6 @@ import android.preference.PreferenceManager;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.ServiceList; import org.schabi.newpipe.extractor.ServiceList;
@ -31,6 +30,18 @@ public class ServiceHelper {
} }
} }
public static String getTranslatedFilterString(String filter, Context c) {
switch(filter) {
case "all": return c.getString(R.string.all);
case "videos": return c.getString(R.string.videos);
case "channels": return c.getString(R.string.channels);
case "playlists": return c.getString(R.string.playlists);
case "tracks": return c.getString(R.string.tracks);
case "users": return c.getString(R.string.users);
default: return filter;
}
}
/** /**
* Get a resource string with instructions for importing subscriptions for each service. * Get a resource string with instructions for importing subscriptions for each service.
* *

View File

@ -125,7 +125,12 @@
<string name="error_report_title">Error report</string> <string name="error_report_title">Error report</string>
<string name="all">All</string> <string name="all">All</string>
<string name="channel">Channel</string> <string name="channel">Channel</string>
<string name="channels">Channels</string>
<string name="playlist">Playlist</string> <string name="playlist">Playlist</string>
<string name="playlists">Playlists</string>
<string name="videos">Videos</string>
<string name="tracks">Tracks</string>
<string name="users">Users</string>
<string name="yes">Yes</string> <string name="yes">Yes</string>
<string name="later">Later</string> <string name="later">Later</string>
<string name="disabled">Disabled</string> <string name="disabled">Disabled</string>

View File

@ -6,7 +6,7 @@ buildscript {
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.2' classpath 'com.android.tools.build:gradle:3.1.3'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files