mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-11-04 01:03:00 +00:00 
			
		
		
		
	Merge branch 'search' into dev
This commit is contained in:
		@@ -54,7 +54,7 @@ dependencies {
 | 
			
		||||
        exclude module: 'support-annotations'
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    implementation 'com.github.TeamNewPipe:NewPipeExtractor:bf1c771'
 | 
			
		||||
    implementation 'com.github.TeamNewPipe:NewPipeExtractor:1eff8c5708'
 | 
			
		||||
 | 
			
		||||
    testImplementation 'junit:junit:4.12'
 | 
			
		||||
    testImplementation 'org.mockito:mockito-core:2.8.9'
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,8 @@ import org.schabi.newpipe.util.ServiceHelper;
 | 
			
		||||
import org.schabi.newpipe.util.StateSaver;
 | 
			
		||||
import org.schabi.newpipe.util.ThemeHelper;
 | 
			
		||||
 | 
			
		||||
import static org.schabi.newpipe.extractor.InfoItem.InfoType.PLAYLIST;
 | 
			
		||||
 | 
			
		||||
public class MainActivity extends AppCompatActivity {
 | 
			
		||||
    private static final String TAG = "MainActivity";
 | 
			
		||||
    public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
 | 
			
		||||
@@ -392,31 +394,45 @@ public class MainActivity extends AppCompatActivity {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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)) {
 | 
			
		||||
            String url = intent.getStringExtra(Constants.KEY_URL);
 | 
			
		||||
            int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
 | 
			
		||||
            String title = intent.getStringExtra(Constants.KEY_TITLE);
 | 
			
		||||
            switch (((StreamingService.LinkType) intent.getSerializableExtra(Constants.KEY_LINK_TYPE))) {
 | 
			
		||||
                case STREAM:
 | 
			
		||||
                    boolean autoPlay = intent.getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false);
 | 
			
		||||
                    NavigationHelper.openVideoDetailFragment(getSupportFragmentManager(), serviceId, url, title, autoPlay);
 | 
			
		||||
                    break;
 | 
			
		||||
                case CHANNEL:
 | 
			
		||||
                    NavigationHelper.openChannelFragment(getSupportFragmentManager(), serviceId, url, title);
 | 
			
		||||
                    break;
 | 
			
		||||
                case PLAYLIST:
 | 
			
		||||
                    NavigationHelper.openPlaylistFragment(getSupportFragmentManager(), serviceId, url, title);
 | 
			
		||||
                    break;
 | 
			
		||||
            if (intent.hasExtra(Constants.KEY_LINK_TYPE)) {
 | 
			
		||||
                String url = intent.getStringExtra(Constants.KEY_URL);
 | 
			
		||||
                int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
 | 
			
		||||
                String title = intent.getStringExtra(Constants.KEY_TITLE);
 | 
			
		||||
                switch (((StreamingService.LinkType) intent.getSerializableExtra(Constants.KEY_LINK_TYPE))) {
 | 
			
		||||
                    case STREAM:
 | 
			
		||||
                        boolean autoPlay = intent.getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false);
 | 
			
		||||
                        NavigationHelper.openVideoDetailFragment(getSupportFragmentManager(), serviceId, url, title, autoPlay);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case CHANNEL:
 | 
			
		||||
                        NavigationHelper.openChannelFragment(getSupportFragmentManager(),
 | 
			
		||||
                                serviceId,
 | 
			
		||||
                                url,
 | 
			
		||||
                                title);
 | 
			
		||||
                        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)) {
 | 
			
		||||
            String searchQuery = intent.getStringExtra(Constants.KEY_QUERY);
 | 
			
		||||
            if (searchQuery == null) searchQuery = "";
 | 
			
		||||
            int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
 | 
			
		||||
            NavigationHelper.openSearchFragment(getSupportFragmentManager(), serviceId, searchQuery);
 | 
			
		||||
        } else {
 | 
			
		||||
            NavigationHelper.gotoMainFragment(getSupportFragmentManager());
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            ErrorActivity.reportUiError(this, e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ import android.support.v4.app.FragmentManager;
 | 
			
		||||
import android.support.v4.app.FragmentPagerAdapter;
 | 
			
		||||
import android.support.v4.view.ViewPager;
 | 
			
		||||
import android.support.v7.app.ActionBar;
 | 
			
		||||
import android.support.v7.app.AppCompatActivity;
 | 
			
		||||
import android.support.v7.preference.PreferenceManager;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
@@ -127,7 +128,14 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
 | 
			
		||||
    public boolean onOptionsItemSelected(MenuItem item) {
 | 
			
		||||
        switch (item.getItemId()) {
 | 
			
		||||
            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 super.onOptionsItemSelected(item);
 | 
			
		||||
@@ -226,7 +234,9 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
 | 
			
		||||
                        FALLBACK_CHANNEL_URL);
 | 
			
		||||
                String name = preferences.getString(getString(R.string.main_page_selected_channel_name),
 | 
			
		||||
                        FALLBACK_CHANNEL_NAME);
 | 
			
		||||
                ChannelFragment fragment = ChannelFragment.getInstance(serviceId, url, name);
 | 
			
		||||
                ChannelFragment fragment = ChannelFragment.getInstance(serviceId,
 | 
			
		||||
                        url,
 | 
			
		||||
                        name);
 | 
			
		||||
                fragment.useAsFrontPage(true);
 | 
			
		||||
                return fragment;
 | 
			
		||||
            } else {
 | 
			
		||||
@@ -255,20 +265,13 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
 | 
			
		||||
        for (final String ks : kl.getAvailableKiosks()) {
 | 
			
		||||
            menu.add(0, KIOSK_MENU_OFFSET + i, Menu.NONE,
 | 
			
		||||
                    KioskTranslator.getTranslatedKioskName(ks, getContext()))
 | 
			
		||||
                    .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
 | 
			
		||||
                        @Override
 | 
			
		||||
                        public boolean onMenuItemClick(MenuItem menuItem) {
 | 
			
		||||
                    .setOnMenuItemClickListener(menuItem -> {
 | 
			
		||||
                            try {
 | 
			
		||||
                                NavigationHelper.openKioskFragment(getFragmentManager(), currentServiceId, ks);
 | 
			
		||||
                            } catch (Exception e) {
 | 
			
		||||
                                ErrorActivity.reportError(activity, e,
 | 
			
		||||
                                        activity.getClass(),
 | 
			
		||||
                                        null,
 | 
			
		||||
                                        ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
 | 
			
		||||
                                                "none", "", R.string.app_ui_crash));
 | 
			
		||||
                                ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
 | 
			
		||||
                            }
 | 
			
		||||
                            return true;
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
            i++;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ import android.support.v4.content.ContextCompat;
 | 
			
		||||
import android.support.v4.view.animation.FastOutSlowInInterpolator;
 | 
			
		||||
import android.support.v7.app.ActionBar;
 | 
			
		||||
import android.support.v7.app.AlertDialog;
 | 
			
		||||
import android.support.v7.app.AppCompatActivity;
 | 
			
		||||
import android.text.Html;
 | 
			
		||||
import android.text.Spanned;
 | 
			
		||||
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.exceptions.ContentNotAvailableException;
 | 
			
		||||
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.Stream;
 | 
			
		||||
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.BaseStateFragment;
 | 
			
		||||
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.StreamSizeWrapper;
 | 
			
		||||
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
 | 
			
		||||
@@ -365,11 +367,15 @@ public class VideoDetailFragment
 | 
			
		||||
                if (TextUtils.isEmpty(currentInfo.getUploaderUrl())) {
 | 
			
		||||
                    Log.w(TAG, "Can't open channel because we got no channel URL");
 | 
			
		||||
                } else {
 | 
			
		||||
                    NavigationHelper.openChannelFragment(
 | 
			
		||||
                            getFragmentManager(),
 | 
			
		||||
                            currentInfo.getServiceId(),
 | 
			
		||||
                            currentInfo.getUploaderUrl(),
 | 
			
		||||
                            currentInfo.getUploaderName());
 | 
			
		||||
                    try {
 | 
			
		||||
                        NavigationHelper.openChannelFragment(
 | 
			
		||||
                                getFragmentManager(),
 | 
			
		||||
                                currentInfo.getServiceId(),
 | 
			
		||||
                                currentInfo.getUploaderUrl(),
 | 
			
		||||
                                currentInfo.getUploaderName());
 | 
			
		||||
                    } catch (Exception e) {
 | 
			
		||||
                        ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case R.id.detail_thumbnail_root_layout:
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ import android.content.DialogInterface;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.support.annotation.NonNull;
 | 
			
		||||
import android.support.v7.app.ActionBar;
 | 
			
		||||
import android.support.v7.app.AppCompatActivity;
 | 
			
		||||
import android.support.v7.widget.LinearLayoutManager;
 | 
			
		||||
import android.support.v7.widget.RecyclerView;
 | 
			
		||||
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.InfoListAdapter;
 | 
			
		||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
 | 
			
		||||
import org.schabi.newpipe.report.ErrorActivity;
 | 
			
		||||
import org.schabi.newpipe.util.NavigationHelper;
 | 
			
		||||
import org.schabi.newpipe.util.OnClickGesture;
 | 
			
		||||
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>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void selected(ChannelInfoItem selectedItem) {
 | 
			
		||||
                onItemSelected(selectedItem);
 | 
			
		||||
                NavigationHelper.openChannelFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(),
 | 
			
		||||
                        selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
 | 
			
		||||
                try {
 | 
			
		||||
                    onItemSelected(selectedItem);
 | 
			
		||||
                    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>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void selected(PlaylistInfoItem selectedItem) {
 | 
			
		||||
                onItemSelected(selectedItem);
 | 
			
		||||
                NavigationHelper.openPlaylistFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(),
 | 
			
		||||
                        selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
 | 
			
		||||
                try {
 | 
			
		||||
                    onItemSelected(selectedItem);
 | 
			
		||||
                    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) {
 | 
			
		||||
        onItemSelected(selectedItem);
 | 
			
		||||
        NavigationHelper.openVideoDetailFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(),
 | 
			
		||||
        NavigationHelper.openVideoDetailFragment(useAsFrontPage
 | 
			
		||||
                        ? getParentFragment().getFragmentManager()
 | 
			
		||||
                        : getFragmentManager(),
 | 
			
		||||
                selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,9 @@ import android.view.View;
 | 
			
		||||
 | 
			
		||||
import org.schabi.newpipe.extractor.ListExtractor;
 | 
			
		||||
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 java.util.Queue;
 | 
			
		||||
@@ -166,7 +169,6 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
 | 
			
		||||
    public void handleResult(@NonNull I result) {
 | 
			
		||||
        super.handleResult(result);
 | 
			
		||||
 | 
			
		||||
        url = result.getUrl();
 | 
			
		||||
        name = result.getName();
 | 
			
		||||
        setTitle(name);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,7 @@ import org.schabi.newpipe.extractor.NewPipe;
 | 
			
		||||
import org.schabi.newpipe.extractor.channel.ChannelInfo;
 | 
			
		||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
 | 
			
		||||
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.info_list.InfoItemDialog;
 | 
			
		||||
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
 | 
			
		||||
@@ -501,7 +502,11 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
 | 
			
		||||
        if (super.onError(exception)) return true;
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,22 +11,20 @@ import android.view.Menu;
 | 
			
		||||
import android.view.MenuInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.ViewGroup;
 | 
			
		||||
import android.widget.TextView;
 | 
			
		||||
 | 
			
		||||
import org.schabi.newpipe.R;
 | 
			
		||||
import org.schabi.newpipe.extractor.ListExtractor;
 | 
			
		||||
import org.schabi.newpipe.extractor.NewPipe;
 | 
			
		||||
import org.schabi.newpipe.extractor.StreamingService;
 | 
			
		||||
import org.schabi.newpipe.extractor.UrlIdHandler;
 | 
			
		||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
 | 
			
		||||
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.info_list.InfoItemBuilder;
 | 
			
		||||
import org.schabi.newpipe.report.UserAction;
 | 
			
		||||
import org.schabi.newpipe.util.ExtractorHelper;
 | 
			
		||||
import org.schabi.newpipe.util.KioskTranslator;
 | 
			
		||||
import org.schabi.newpipe.util.NavigationHelper;
 | 
			
		||||
 | 
			
		||||
import icepick.State;
 | 
			
		||||
import io.reactivex.Single;
 | 
			
		||||
@@ -74,10 +72,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
 | 
			
		||||
            throws ExtractionException {
 | 
			
		||||
        KioskFragment instance = new KioskFragment();
 | 
			
		||||
        StreamingService service = NewPipe.getService(serviceId);
 | 
			
		||||
        UrlIdHandler kioskTypeUrlIdHandler = service.getKioskList()
 | 
			
		||||
                .getUrlIdHandlerByType(kioskId);
 | 
			
		||||
        ListLinkHandlerFactory kioskLinkHandlerFactory = service.getKioskList()
 | 
			
		||||
                .getListLinkHandlerFactoryByType(kioskId);
 | 
			
		||||
        instance.setInitialData(serviceId,
 | 
			
		||||
                kioskTypeUrlIdHandler.getUrl(kioskId), kioskId);
 | 
			
		||||
                kioskLinkHandlerFactory.fromId(kioskId).getUrl(), kioskId);
 | 
			
		||||
        instance.kioskId = kioskId;
 | 
			
		||||
        return instance;
 | 
			
		||||
    }
 | 
			
		||||
@@ -136,7 +134,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
 | 
			
		||||
                .getDefaultSharedPreferences(activity)
 | 
			
		||||
                .getString(getString(R.string.content_country_key),
 | 
			
		||||
                        getString(R.string.default_country_value));
 | 
			
		||||
        return ExtractorHelper.getKioskInfo(serviceId, url, contentCountry, forceReload);
 | 
			
		||||
        return ExtractorHelper.getKioskInfo(serviceId,
 | 
			
		||||
                url,
 | 
			
		||||
                contentCountry,
 | 
			
		||||
                forceReload);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -145,7 +146,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
 | 
			
		||||
                .getDefaultSharedPreferences(activity)
 | 
			
		||||
                .getString(getString(R.string.content_country_key),
 | 
			
		||||
                        getString(R.string.default_country_value));
 | 
			
		||||
        return ExtractorHelper.getMoreKioskItems(serviceId, url, currentNextPageUrl, contentCountry);
 | 
			
		||||
        return ExtractorHelper.getMoreKioskItems(serviceId,
 | 
			
		||||
                url,
 | 
			
		||||
                currentNextPageUrl,
 | 
			
		||||
                contentCountry);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*//////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ import android.content.DialogInterface;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.support.annotation.NonNull;
 | 
			
		||||
import android.support.annotation.Nullable;
 | 
			
		||||
import android.support.v7.app.AppCompatActivity;
 | 
			
		||||
import android.text.TextUtils;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
@@ -19,6 +20,7 @@ import android.widget.TextView;
 | 
			
		||||
 | 
			
		||||
import org.reactivestreams.Subscriber;
 | 
			
		||||
import org.reactivestreams.Subscription;
 | 
			
		||||
import org.schabi.newpipe.App;
 | 
			
		||||
import org.schabi.newpipe.NewPipeDatabase;
 | 
			
		||||
import org.schabi.newpipe.R;
 | 
			
		||||
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.playlist.PlaylistInfo;
 | 
			
		||||
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.info_list.InfoItemDialog;
 | 
			
		||||
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
 | 
			
		||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
 | 
			
		||||
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue;
 | 
			
		||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
 | 
			
		||||
import org.schabi.newpipe.report.ErrorActivity;
 | 
			
		||||
import org.schabi.newpipe.report.UserAction;
 | 
			
		||||
import org.schabi.newpipe.util.ExtractorHelper;
 | 
			
		||||
import org.schabi.newpipe.util.ImageDisplayConstants;
 | 
			
		||||
@@ -267,11 +271,16 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
 | 
			
		||||
        if (!TextUtils.isEmpty(result.getUploaderName())) {
 | 
			
		||||
            headerUploaderName.setText(result.getUploaderName());
 | 
			
		||||
            if (!TextUtils.isEmpty(result.getUploaderUrl())) {
 | 
			
		||||
                headerUploaderLayout.setOnClickListener(v ->
 | 
			
		||||
                headerUploaderLayout.setOnClickListener(v -> {
 | 
			
		||||
                    try {
 | 
			
		||||
                        NavigationHelper.openChannelFragment(getFragmentManager(),
 | 
			
		||||
                                result.getServiceId(), result.getUploaderUrl(),
 | 
			
		||||
                                result.getUploaderName())
 | 
			
		||||
                );
 | 
			
		||||
                                result.getServiceId(),
 | 
			
		||||
                                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;
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,8 @@ import android.view.inputmethod.InputMethodManager;
 | 
			
		||||
import android.widget.EditText;
 | 
			
		||||
import android.widget.TextView;
 | 
			
		||||
 | 
			
		||||
import com.facebook.stetho.common.ListUtil;
 | 
			
		||||
 | 
			
		||||
import org.schabi.newpipe.R;
 | 
			
		||||
import org.schabi.newpipe.ReCaptchaActivity;
 | 
			
		||||
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.StreamingService;
 | 
			
		||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
 | 
			
		||||
import org.schabi.newpipe.extractor.search.SearchEngine;
 | 
			
		||||
import org.schabi.newpipe.extractor.search.SearchResult;
 | 
			
		||||
import org.schabi.newpipe.extractor.search.SearchExtractor;
 | 
			
		||||
import org.schabi.newpipe.extractor.search.SearchInfo;
 | 
			
		||||
import org.schabi.newpipe.fragments.BackPressable;
 | 
			
		||||
import org.schabi.newpipe.fragments.list.BaseListFragment;
 | 
			
		||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
 | 
			
		||||
import org.schabi.newpipe.report.ErrorActivity;
 | 
			
		||||
import org.schabi.newpipe.report.UserAction;
 | 
			
		||||
import org.schabi.newpipe.util.Constants;
 | 
			
		||||
import org.schabi.newpipe.util.AnimationUtils;
 | 
			
		||||
import org.schabi.newpipe.util.ExtractorHelper;
 | 
			
		||||
import org.schabi.newpipe.util.LayoutManagerSmoothScroller;
 | 
			
		||||
import org.schabi.newpipe.util.NavigationHelper;
 | 
			
		||||
import org.schabi.newpipe.util.ServiceHelper;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InterruptedIOException;
 | 
			
		||||
import java.net.SocketException;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Iterator;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Queue;
 | 
			
		||||
import java.util.concurrent.Callable;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
 | 
			
		||||
import icepick.State;
 | 
			
		||||
@@ -65,14 +69,15 @@ import io.reactivex.Observable;
 | 
			
		||||
import io.reactivex.android.schedulers.AndroidSchedulers;
 | 
			
		||||
import io.reactivex.disposables.CompositeDisposable;
 | 
			
		||||
import io.reactivex.disposables.Disposable;
 | 
			
		||||
import io.reactivex.functions.Consumer;
 | 
			
		||||
import io.reactivex.schedulers.Schedulers;
 | 
			
		||||
import io.reactivex.subjects.PublishSubject;
 | 
			
		||||
 | 
			
		||||
import static java.util.Arrays.asList;
 | 
			
		||||
 | 
			
		||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
 | 
			
		||||
 | 
			
		||||
public class SearchFragment
 | 
			
		||||
        extends BaseListFragment<SearchResult, ListExtractor.InfoItemsPage>
 | 
			
		||||
        extends BaseListFragment<SearchInfo, ListExtractor.InfoItemsPage>
 | 
			
		||||
        implements BackPressable {
 | 
			
		||||
 | 
			
		||||
    /*//////////////////////////////////////////////////////////////////////////
 | 
			
		||||
@@ -92,19 +97,28 @@ public class SearchFragment
 | 
			
		||||
 | 
			
		||||
    @State
 | 
			
		||||
    protected int filterItemCheckedId = -1;
 | 
			
		||||
    private SearchEngine.Filter filter = SearchEngine.Filter.ANY;
 | 
			
		||||
 | 
			
		||||
    @State
 | 
			
		||||
    protected int serviceId = Constants.NO_SERVICE_ID;
 | 
			
		||||
    
 | 
			
		||||
    // this three represet the current search query
 | 
			
		||||
    @State
 | 
			
		||||
    protected String searchQuery;
 | 
			
		||||
    protected String searchString;
 | 
			
		||||
    @State
 | 
			
		||||
    protected String lastSearchedQuery;
 | 
			
		||||
    protected String[] contentFilter;
 | 
			
		||||
    @State
 | 
			
		||||
    protected String sortFilter;
 | 
			
		||||
    
 | 
			
		||||
    // these represtent the last search
 | 
			
		||||
    @State
 | 
			
		||||
    protected String lastSearchedString;
 | 
			
		||||
    
 | 
			
		||||
    @State
 | 
			
		||||
    protected boolean wasSearchFocused = false;
 | 
			
		||||
 | 
			
		||||
    private int currentPage = 0;
 | 
			
		||||
    private int currentNextPage = 0;
 | 
			
		||||
    private StreamingService service;
 | 
			
		||||
    private String currentPageUrl;
 | 
			
		||||
    private String nextPageUrl;
 | 
			
		||||
    private String contentCountry;
 | 
			
		||||
    private boolean isSuggestionsEnabled = 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.setQuery(serviceId, query);
 | 
			
		||||
        searchFragment.setQuery(serviceId, searchString, new String[0], "");
 | 
			
		||||
 | 
			
		||||
        if (!TextUtils.isEmpty(query)) {
 | 
			
		||||
        if (!TextUtils.isEmpty(searchString)) {
 | 
			
		||||
            searchFragment.setSearchOnResume();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -202,13 +216,22 @@ public class SearchFragment
 | 
			
		||||
        if (DEBUG) Log.d(TAG, "onResume() called");
 | 
			
		||||
        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 (currentNextPage > currentPage) loadMoreItems();
 | 
			
		||||
                else search(searchQuery);
 | 
			
		||||
                search(searchString, contentFilter, sortFilter);
 | 
			
		||||
            } else if (infoListAdapter.getItemsList().size() == 0) {
 | 
			
		||||
                if (savedState == null) {
 | 
			
		||||
                    search(searchQuery);
 | 
			
		||||
                    search(searchString, contentFilter, sortFilter);
 | 
			
		||||
                } else if (!isLoading.get() && !wasSearchFocused) {
 | 
			
		||||
                    infoListAdapter.clearStreamItemList();
 | 
			
		||||
                    showEmptyState();
 | 
			
		||||
@@ -218,7 +241,7 @@ public class SearchFragment
 | 
			
		||||
 | 
			
		||||
        if (suggestionDisposable == null || suggestionDisposable.isDisposed()) initSuggestionObserver();
 | 
			
		||||
 | 
			
		||||
        if (TextUtils.isEmpty(searchQuery) || wasSearchFocused) {
 | 
			
		||||
        if (TextUtils.isEmpty(searchString) || wasSearchFocused) {
 | 
			
		||||
            showKeyboardSearch();
 | 
			
		||||
            showSuggestionsPanel();
 | 
			
		||||
        } else {
 | 
			
		||||
@@ -247,8 +270,9 @@ public class SearchFragment
 | 
			
		||||
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
 | 
			
		||||
        switch (requestCode) {
 | 
			
		||||
            case ReCaptchaActivity.RECAPTCHA_REQUEST:
 | 
			
		||||
                if (resultCode == Activity.RESULT_OK && !TextUtils.isEmpty(searchQuery)) {
 | 
			
		||||
                    search(searchQuery);
 | 
			
		||||
                if (resultCode == Activity.RESULT_OK
 | 
			
		||||
                        && !TextUtils.isEmpty(searchString)) {
 | 
			
		||||
                    search(searchString, contentFilter, sortFilter);
 | 
			
		||||
                } else Log.e(TAG, "ReCaptcha failed");
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
@@ -282,20 +306,22 @@ public class SearchFragment
 | 
			
		||||
    @Override
 | 
			
		||||
    public void writeTo(Queue<Object> objectsToSave) {
 | 
			
		||||
        super.writeTo(objectsToSave);
 | 
			
		||||
        objectsToSave.add(currentPage);
 | 
			
		||||
        objectsToSave.add(currentNextPage);
 | 
			
		||||
        objectsToSave.add(currentPageUrl);
 | 
			
		||||
        objectsToSave.add(nextPageUrl);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void readFrom(@NonNull Queue<Object> savedObjects) throws Exception {
 | 
			
		||||
        super.readFrom(savedObjects);
 | 
			
		||||
        currentPage = (int) savedObjects.poll();
 | 
			
		||||
        currentNextPage = (int) savedObjects.poll();
 | 
			
		||||
        currentPageUrl = (String) savedObjects.poll();
 | 
			
		||||
        nextPageUrl = (String) savedObjects.poll();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onSaveInstanceState(Bundle bundle) {
 | 
			
		||||
        searchQuery = searchEditText != null ? searchEditText.getText().toString() : searchQuery;
 | 
			
		||||
        searchString = searchEditText != null
 | 
			
		||||
                ? searchEditText.getText().toString()
 | 
			
		||||
                : searchString;
 | 
			
		||||
        super.onSaveInstanceState(bundle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -305,8 +331,11 @@ public class SearchFragment
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void reloadContent() {
 | 
			
		||||
        if (!TextUtils.isEmpty(searchQuery) || (searchEditText != null && !TextUtils.isEmpty(searchEditText.getText()))) {
 | 
			
		||||
            search(!TextUtils.isEmpty(searchQuery) ? searchQuery : searchEditText.getText().toString());
 | 
			
		||||
        if (!TextUtils.isEmpty(searchString)
 | 
			
		||||
                || (searchEditText != null && !TextUtils.isEmpty(searchEditText.getText()))) {
 | 
			
		||||
            search(!TextUtils.isEmpty(searchString)
 | 
			
		||||
                    ? searchString
 | 
			
		||||
                    : searchEditText.getText().toString(), new String[0], "");
 | 
			
		||||
        } else {
 | 
			
		||||
            if (searchEditText != null) {
 | 
			
		||||
                searchEditText.setText("");
 | 
			
		||||
@@ -330,22 +359,32 @@ public class SearchFragment
 | 
			
		||||
            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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onOptionsItemSelected(MenuItem item) {
 | 
			
		||||
        switch (item.getItemId()) {
 | 
			
		||||
            case R.id.menu_filter_all:
 | 
			
		||||
            case R.id.menu_filter_video:
 | 
			
		||||
            case R.id.menu_filter_channel:
 | 
			
		||||
            case R.id.menu_filter_playlist:
 | 
			
		||||
                changeFilter(item, getFilterFromMenuId(item.getItemId()));
 | 
			
		||||
                return true;
 | 
			
		||||
            default:
 | 
			
		||||
                return super.onOptionsItemSelected(item);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        List<String> contentFilter = new ArrayList<>(1);
 | 
			
		||||
        contentFilter.add(item.getTitle().toString());
 | 
			
		||||
        changeContentFilter(item, contentFilter);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void restoreFilterChecked(Menu menu, int itemId) {
 | 
			
		||||
@@ -354,21 +393,6 @@ public class SearchFragment
 | 
			
		||||
            if (item == null) return;
 | 
			
		||||
 | 
			
		||||
            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 void showSearchOnStart() {
 | 
			
		||||
        if (DEBUG) Log.d(TAG, "showSearchOnStart() called, searchQuery → " + searchQuery+", lastSearchedQuery → " + lastSearchedQuery);
 | 
			
		||||
        searchEditText.setText(searchQuery);
 | 
			
		||||
        if (DEBUG) Log.d(TAG, "showSearchOnStart() called, 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.setAlpha(0f);
 | 
			
		||||
            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 {
 | 
			
		||||
            searchToolbarContainer.setTranslationX(0);
 | 
			
		||||
            searchToolbarContainer.setAlpha(1f);
 | 
			
		||||
@@ -396,47 +427,38 @@ public class SearchFragment
 | 
			
		||||
 | 
			
		||||
    private void initSearchListeners() {
 | 
			
		||||
        if (DEBUG) Log.d(TAG, "initSearchListeners() called");
 | 
			
		||||
        searchClear.setOnClickListener(new View.OnClickListener() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onClick(View v) {
 | 
			
		||||
                if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]");
 | 
			
		||||
                if (TextUtils.isEmpty(searchEditText.getText())) {
 | 
			
		||||
                    NavigationHelper.gotoMainFragment(getFragmentManager());
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                searchEditText.setText("");
 | 
			
		||||
                suggestionListAdapter.setItems(new ArrayList<SuggestionItem>());
 | 
			
		||||
                showKeyboardSearch();
 | 
			
		||||
        searchClear.setOnClickListener(v -> {
 | 
			
		||||
            if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]");
 | 
			
		||||
            if (TextUtils.isEmpty(searchEditText.getText())) {
 | 
			
		||||
                NavigationHelper.gotoMainFragment(getFragmentManager());
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            searchEditText.setText("");
 | 
			
		||||
            suggestionListAdapter.setItems(new ArrayList<>());
 | 
			
		||||
            showKeyboardSearch();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        TooltipCompat.setTooltipText(searchClear, getString(R.string.clear));
 | 
			
		||||
 | 
			
		||||
        searchEditText.setOnClickListener(new View.OnClickListener() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onClick(View v) {
 | 
			
		||||
                if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]");
 | 
			
		||||
                if (isSuggestionsEnabled && errorPanelRoot.getVisibility() != View.VISIBLE) {
 | 
			
		||||
                    showSuggestionsPanel();
 | 
			
		||||
                }
 | 
			
		||||
        searchEditText.setOnClickListener(v -> {
 | 
			
		||||
            if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]");
 | 
			
		||||
            if (isSuggestionsEnabled && errorPanelRoot.getVisibility() != View.VISIBLE) {
 | 
			
		||||
                showSuggestionsPanel();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        searchEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onFocusChange(View v, boolean hasFocus) {
 | 
			
		||||
                if (DEBUG) Log.d(TAG, "onFocusChange() called with: v = [" + v + "], hasFocus = [" + hasFocus + "]");
 | 
			
		||||
                if (isSuggestionsEnabled && hasFocus && errorPanelRoot.getVisibility() != View.VISIBLE) {
 | 
			
		||||
                    showSuggestionsPanel();
 | 
			
		||||
                }
 | 
			
		||||
        searchEditText.setOnFocusChangeListener((View v, boolean hasFocus) -> {
 | 
			
		||||
            if (DEBUG) Log.d(TAG, "onFocusChange() called with: v = [" + v + "], hasFocus = [" + hasFocus + "]");
 | 
			
		||||
            if (isSuggestionsEnabled && hasFocus && errorPanelRoot.getVisibility() != View.VISIBLE) {
 | 
			
		||||
                showSuggestionsPanel();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        suggestionListAdapter.setListener(new SuggestionListAdapter.OnSuggestionItemSelected() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onSuggestionItemSelected(SuggestionItem item) {
 | 
			
		||||
                search(item.query);
 | 
			
		||||
                search(item.query, new String[0], "");
 | 
			
		||||
                searchEditText.setText(item.query);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -469,21 +491,22 @@ public class SearchFragment
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        searchEditText.addTextChangedListener(textWatcher);
 | 
			
		||||
        searchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
 | 
			
		||||
                if (DEBUG) {
 | 
			
		||||
                    Log.d(TAG, "onEditorAction() called with: v = [" + v + "], actionId = [" + actionId + "], event = [" + event + "]");
 | 
			
		||||
                }
 | 
			
		||||
                if (event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER || event.getAction() == EditorInfo.IME_ACTION_SEARCH)) {
 | 
			
		||||
                    search(searchEditText.getText().toString());
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        searchEditText.setOnEditorActionListener(
 | 
			
		||||
                (TextView v, int actionId, KeyEvent event) -> {
 | 
			
		||||
                    if (DEBUG) {
 | 
			
		||||
                        Log.d(TAG, "onEditorAction() called with: v = [" + v + "], actionId = [" + actionId + "], event = [" + event + "]");
 | 
			
		||||
                    }
 | 
			
		||||
                    if (event != null
 | 
			
		||||
                            && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER
 | 
			
		||||
                                || event.getAction() == EditorInfo.IME_ACTION_SEARCH)) {
 | 
			
		||||
                        search(searchEditText.getText().toString(), new String[0], "");
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
                    return false;
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
        if (suggestionDisposable == null || suggestionDisposable.isDisposed()) initSuggestionObserver();
 | 
			
		||||
        if (suggestionDisposable == null || suggestionDisposable.isDisposed())
 | 
			
		||||
            initSuggestionObserver();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void unsetSearchListeners() {
 | 
			
		||||
@@ -513,7 +536,8 @@ public class SearchFragment
 | 
			
		||||
        if (searchEditText == null) return;
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -522,8 +546,10 @@ public class SearchFragment
 | 
			
		||||
        if (DEBUG) Log.d(TAG, "hideKeyboardSearch() called");
 | 
			
		||||
        if (searchEditText == null) return;
 | 
			
		||||
 | 
			
		||||
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
 | 
			
		||||
        imm.hideSoftInputFromWindow(searchEditText.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
 | 
			
		||||
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(
 | 
			
		||||
                Context.INPUT_METHOD_SERVICE);
 | 
			
		||||
        imm.hideSoftInputFromWindow(searchEditText.getWindowToken(),
 | 
			
		||||
                InputMethodManager.HIDE_NOT_ALWAYS);
 | 
			
		||||
 | 
			
		||||
        searchEditText.clearFocus();
 | 
			
		||||
    }
 | 
			
		||||
@@ -554,10 +580,12 @@ public class SearchFragment
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    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();
 | 
			
		||||
            hideKeyboardSearch();
 | 
			
		||||
            searchEditText.setText(lastSearchedQuery);
 | 
			
		||||
            searchEditText.setText(lastSearchedString);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -573,8 +601,10 @@ public class SearchFragment
 | 
			
		||||
 | 
			
		||||
        final Observable<String> observable = suggestionPublisher
 | 
			
		||||
                .debounce(SUGGESTIONS_DEBOUNCE, TimeUnit.MILLISECONDS)
 | 
			
		||||
                .startWith(searchQuery != null ? searchQuery : "")
 | 
			
		||||
                .filter(query -> isSuggestionsEnabled);
 | 
			
		||||
                .startWith(searchString != null
 | 
			
		||||
                        ? searchString
 | 
			
		||||
                        : "")
 | 
			
		||||
                .filter(searchString -> isSuggestionsEnabled);
 | 
			
		||||
 | 
			
		||||
        suggestionDisposable = observable
 | 
			
		||||
                .switchMap(query -> {
 | 
			
		||||
@@ -645,56 +675,44 @@ public class SearchFragment
 | 
			
		||||
        // no-op
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void search(final String query) {
 | 
			
		||||
        if (DEBUG) Log.d(TAG, "search() called with: query = [" + query + "]");
 | 
			
		||||
        if (query.isEmpty()) return;
 | 
			
		||||
    private void search(final String searchString, String[] contentFilter, String sortFilter) {
 | 
			
		||||
        if (DEBUG) Log.d(TAG, "search() called with: query = [" + searchString + "]");
 | 
			
		||||
        if (searchString.isEmpty()) return;
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            final StreamingService service = NewPipe.getServiceByUrl(query);
 | 
			
		||||
            final StreamingService service = NewPipe.getServiceByUrl(searchString);
 | 
			
		||||
            if (service != null) {
 | 
			
		||||
                showLoading();
 | 
			
		||||
                disposables.add(Observable
 | 
			
		||||
                        .fromCallable(new Callable<Intent>() {
 | 
			
		||||
                            @Override
 | 
			
		||||
                            public Intent call() throws Exception {
 | 
			
		||||
                                return NavigationHelper.getIntentByLink(activity, service, query);
 | 
			
		||||
                            }
 | 
			
		||||
                        })
 | 
			
		||||
                        .fromCallable(() ->
 | 
			
		||||
                                NavigationHelper.getIntentByLink(activity, service, searchString))
 | 
			
		||||
                        .subscribeOn(Schedulers.io())
 | 
			
		||||
                        .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
                        .subscribe(new Consumer<Intent>() {
 | 
			
		||||
                            @Override
 | 
			
		||||
                            public void accept(Intent intent) throws Exception {
 | 
			
		||||
                                getFragmentManager().popBackStackImmediate();
 | 
			
		||||
                                activity.startActivity(intent);
 | 
			
		||||
                            }
 | 
			
		||||
                        }, new Consumer<Throwable>() {
 | 
			
		||||
                            @Override
 | 
			
		||||
                            public void accept(Throwable throwable) throws Exception {
 | 
			
		||||
                                showError(getString(R.string.url_not_supported_toast), false);
 | 
			
		||||
                            }
 | 
			
		||||
                        }));
 | 
			
		||||
                        .subscribe(intent -> {
 | 
			
		||||
                            getFragmentManager().popBackStackImmediate();
 | 
			
		||||
                            activity.startActivity(intent);
 | 
			
		||||
                        }, throwable ->
 | 
			
		||||
                                showError(getString(R.string.url_not_supported_toast), false)));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            // Exception occurred, it's not a url
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        lastSearchedQuery = query;
 | 
			
		||||
        searchQuery = query;
 | 
			
		||||
        currentPage = 0;
 | 
			
		||||
        lastSearchedString = this.searchString;
 | 
			
		||||
        this.searchString = searchString;
 | 
			
		||||
        infoListAdapter.clearStreamItemList();
 | 
			
		||||
        hideSuggestionsPanel();
 | 
			
		||||
        hideKeyboardSearch();
 | 
			
		||||
 | 
			
		||||
        historyRecordManager.onSearched(serviceId, query)
 | 
			
		||||
        historyRecordManager.onSearched(serviceId, searchString)
 | 
			
		||||
                .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
                .subscribe(
 | 
			
		||||
                        ignored -> {},
 | 
			
		||||
                        error -> showSnackBarError(error, UserAction.SEARCHED,
 | 
			
		||||
                                NewPipe.getNameOfService(serviceId), query, 0)
 | 
			
		||||
                                NewPipe.getNameOfService(serviceId), searchString, 0)
 | 
			
		||||
                );
 | 
			
		||||
        suggestionPublisher.onNext(query);
 | 
			
		||||
        suggestionPublisher.onNext(searchString);
 | 
			
		||||
        startLoading(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -703,11 +721,16 @@ public class SearchFragment
 | 
			
		||||
        super.startLoading(forceLoad);
 | 
			
		||||
        if (disposables != null) disposables.clear();
 | 
			
		||||
        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())
 | 
			
		||||
                .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
                .doOnEvent((searchResult, throwable) -> isLoading.set(false))
 | 
			
		||||
                .subscribe(this::handleResult, this::onError);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -715,8 +738,13 @@ public class SearchFragment
 | 
			
		||||
        isLoading.set(true);
 | 
			
		||||
        showListFooter(true);
 | 
			
		||||
        if (searchDisposable != null) searchDisposable.dispose();
 | 
			
		||||
        currentNextPage = currentPage + 1;
 | 
			
		||||
        searchDisposable = ExtractorHelper.getMoreSearchItems(serviceId, searchQuery, currentNextPage, contentCountry, filter)
 | 
			
		||||
        searchDisposable = ExtractorHelper.getMoreSearchItems(
 | 
			
		||||
                    serviceId,
 | 
			
		||||
                    searchString,
 | 
			
		||||
                    asList(contentFilter),
 | 
			
		||||
                    sortFilter,
 | 
			
		||||
                    nextPageUrl,
 | 
			
		||||
                    contentCountry)
 | 
			
		||||
                .subscribeOn(Schedulers.io())
 | 
			
		||||
                .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
                .doOnEvent((nextItemsResult, throwable) -> isLoading.set(false))
 | 
			
		||||
@@ -739,19 +767,22 @@ public class SearchFragment
 | 
			
		||||
    // Utils
 | 
			
		||||
    //////////////////////////////////////////////////////////////////////////*/
 | 
			
		||||
 | 
			
		||||
    private void changeFilter(MenuItem item, SearchEngine.Filter filter) {
 | 
			
		||||
        this.filter = filter;
 | 
			
		||||
    private void changeContentFilter(MenuItem item, List<String> contentFilter) {
 | 
			
		||||
        this.filterItemCheckedId = item.getItemId();
 | 
			
		||||
        item.setChecked(true);
 | 
			
		||||
 | 
			
		||||
        if (!TextUtils.isEmpty(searchQuery)) {
 | 
			
		||||
            search(searchQuery);
 | 
			
		||||
        this.contentFilter = new String[] {contentFilter.get(0)};
 | 
			
		||||
 | 
			
		||||
        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.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 (super.onError(exception)) return;
 | 
			
		||||
 | 
			
		||||
        int errorId = exception instanceof ParsingException ? R.string.parsing_error : R.string.general_error;
 | 
			
		||||
        onUnrecoverableError(exception, UserAction.GET_SUGGESTIONS, NewPipe.getNameOfService(serviceId), searchQuery, errorId);
 | 
			
		||||
        int errorId = exception instanceof ParsingException
 | 
			
		||||
                ? 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
 | 
			
		||||
    public void handleResult(@NonNull SearchResult result) {
 | 
			
		||||
        if (!result.errors.isEmpty()) {
 | 
			
		||||
            showSnackBarError(result.errors, UserAction.SEARCHED, NewPipe.getNameOfService(serviceId), searchQuery, 0);
 | 
			
		||||
    public void handleResult(@NonNull SearchInfo result) {
 | 
			
		||||
        if (!result.getErrors().isEmpty()) {
 | 
			
		||||
            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 (!result.getResults().isEmpty()) {
 | 
			
		||||
                infoListAdapter.addInfoItemList(result.getResults());
 | 
			
		||||
            if (!result.getRelatedItems().isEmpty()) {
 | 
			
		||||
                infoListAdapter.addInfoItemList(result.getRelatedItems());
 | 
			
		||||
            } else {
 | 
			
		||||
                infoListAdapter.clearStreamItemList();
 | 
			
		||||
                showEmptyState();
 | 
			
		||||
@@ -821,12 +858,13 @@ public class SearchFragment
 | 
			
		||||
    @Override
 | 
			
		||||
    public void handleNextItems(ListExtractor.InfoItemsPage result) {
 | 
			
		||||
        showListFooter(false);
 | 
			
		||||
        currentPage = Integer.parseInt(result.getNextPageUrl());
 | 
			
		||||
        currentPageUrl = result.getNextPageUrl();
 | 
			
		||||
        infoListAdapter.addInfoItemList(result.getItems());
 | 
			
		||||
 | 
			
		||||
        if (!result.getErrors().isEmpty()) {
 | 
			
		||||
            showSnackBarError(result.getErrors(), UserAction.SEARCHED, NewPipe.getNameOfService(serviceId)
 | 
			
		||||
                    , "\"" + searchQuery + "\" → page " + currentPage, 0);
 | 
			
		||||
            showSnackBarError(result.getErrors(), UserAction.SEARCHED,
 | 
			
		||||
                    NewPipe.getNameOfService(serviceId)
 | 
			
		||||
                    , "\"" + searchString + "\" → page: " + nextPageUrl, 0);
 | 
			
		||||
        }
 | 
			
		||||
        super.handleNextItems(result);
 | 
			
		||||
    }
 | 
			
		||||
@@ -835,12 +873,15 @@ public class SearchFragment
 | 
			
		||||
    protected boolean onError(Throwable exception) {
 | 
			
		||||
        if (super.onError(exception)) return true;
 | 
			
		||||
 | 
			
		||||
        if (exception instanceof SearchEngine.NothingFoundException) {
 | 
			
		||||
        if (exception instanceof SearchExtractor.NothingFoundException) {
 | 
			
		||||
            infoListAdapter.clearStreamItemList();
 | 
			
		||||
            showEmptyState();
 | 
			
		||||
        } else {
 | 
			
		||||
            int errorId = exception instanceof ParsingException ? R.string.parsing_error : R.string.general_error;
 | 
			
		||||
            onUnrecoverableError(exception, UserAction.SEARCHED, NewPipe.getNameOfService(serviceId), searchQuery, errorId);
 | 
			
		||||
            int errorId = exception instanceof ParsingException
 | 
			
		||||
                    ? R.string.parsing_error
 | 
			
		||||
                    : R.string.general_error;
 | 
			
		||||
            onUnrecoverableError(exception, UserAction.SEARCHED,
 | 
			
		||||
                    NewPipe.getNameOfService(serviceId), searchString, errorId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ import android.os.Parcelable;
 | 
			
		||||
import android.support.annotation.NonNull;
 | 
			
		||||
import android.support.annotation.Nullable;
 | 
			
		||||
import android.support.v4.app.FragmentManager;
 | 
			
		||||
import android.support.v7.app.AppCompatActivity;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
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.PlaylistMetadataEntry;
 | 
			
		||||
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.playlist.LocalPlaylistManager;
 | 
			
		||||
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
 | 
			
		||||
import org.schabi.newpipe.report.ErrorActivity;
 | 
			
		||||
import org.schabi.newpipe.report.UserAction;
 | 
			
		||||
import org.schabi.newpipe.util.NavigationHelper;
 | 
			
		||||
import org.schabi.newpipe.util.OnClickGesture;
 | 
			
		||||
@@ -99,19 +102,26 @@ public final class BookmarkFragment
 | 
			
		||||
        itemListAdapter.setSelectedListener(new OnClickGesture<LocalItem>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void selected(LocalItem selectedItem) {
 | 
			
		||||
                // Requires the parent fragment to find holder for fragment replacement
 | 
			
		||||
                if (getParentFragment() == null) return;
 | 
			
		||||
                final FragmentManager fragmentManager = getParentFragment().getFragmentManager();
 | 
			
		||||
                try {
 | 
			
		||||
                    // Requires the parent fragment to find holder for fragment replacement
 | 
			
		||||
                    if (getParentFragment() == null) return;
 | 
			
		||||
                    final FragmentManager fragmentManager = getParentFragment().getFragmentManager();
 | 
			
		||||
 | 
			
		||||
                if (selectedItem instanceof PlaylistMetadataEntry) {
 | 
			
		||||
                    final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem);
 | 
			
		||||
                    NavigationHelper.openLocalPlaylistFragment(fragmentManager, entry.uid,
 | 
			
		||||
                            entry.name);
 | 
			
		||||
                    if (selectedItem instanceof PlaylistMetadataEntry) {
 | 
			
		||||
                        final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem);
 | 
			
		||||
                        NavigationHelper.openLocalPlaylistFragment(fragmentManager, entry.uid,
 | 
			
		||||
                                entry.name);
 | 
			
		||||
 | 
			
		||||
                } else if (selectedItem instanceof PlaylistRemoteEntity) {
 | 
			
		||||
                    final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem);
 | 
			
		||||
                    NavigationHelper.openPlaylistFragment(fragmentManager, entry.getServiceId(),
 | 
			
		||||
                            entry.getUrl(), entry.getName());
 | 
			
		||||
                    } else if (selectedItem instanceof PlaylistRemoteEntity) {
 | 
			
		||||
                        final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem);
 | 
			
		||||
                        NavigationHelper.openPlaylistFragment(
 | 
			
		||||
                                fragmentManager,
 | 
			
		||||
                                entry.getServiceId(),
 | 
			
		||||
                                entry.getUrl(),
 | 
			
		||||
                                entry.getName());
 | 
			
		||||
                    }
 | 
			
		||||
                } catch (Exception e) {
 | 
			
		||||
                    ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ import android.support.annotation.NonNull;
 | 
			
		||||
import android.support.annotation.Nullable;
 | 
			
		||||
import android.support.v4.content.LocalBroadcastManager;
 | 
			
		||||
import android.support.v7.app.ActionBar;
 | 
			
		||||
import android.support.v7.app.AppCompatActivity;
 | 
			
		||||
import android.support.v7.widget.LinearLayoutManager;
 | 
			
		||||
import android.support.v7.widget.RecyclerView;
 | 
			
		||||
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.fragments.BaseStateFragment;
 | 
			
		||||
import org.schabi.newpipe.info_list.InfoListAdapter;
 | 
			
		||||
import org.schabi.newpipe.report.ErrorActivity;
 | 
			
		||||
import org.schabi.newpipe.report.UserAction;
 | 
			
		||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService;
 | 
			
		||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService;
 | 
			
		||||
@@ -318,9 +320,15 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt
 | 
			
		||||
        infoListAdapter.setOnChannelSelectedListener(new OnClickGesture<ChannelInfoItem>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void selected(ChannelInfoItem selectedItem) {
 | 
			
		||||
                // Requires the parent fragment to find holder for fragment replacement
 | 
			
		||||
                NavigationHelper.openChannelFragment(getParentFragment().getFragmentManager(),
 | 
			
		||||
                        selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
 | 
			
		||||
                try {
 | 
			
		||||
                    // Requires the parent fragment to find holder for fragment replacement
 | 
			
		||||
                    NavigationHelper.openChannelFragment(getParentFragment().getFragmentManager(),
 | 
			
		||||
                            selectedItem.getServiceId(),
 | 
			
		||||
                            selectedItem.getUrl(),
 | 
			
		||||
                            selectedItem.getName());
 | 
			
		||||
                } catch (Exception e) {
 | 
			
		||||
                    ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ public class Constants {
 | 
			
		||||
    public static final String KEY_TITLE = "key_title";
 | 
			
		||||
    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_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_MAIN_PAGE_CHANGE = "key_main_page_change";
 | 
			
		||||
 
 | 
			
		||||
@@ -37,9 +37,8 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
 | 
			
		||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
 | 
			
		||||
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
 | 
			
		||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
 | 
			
		||||
import org.schabi.newpipe.extractor.search.SearchEngine;
 | 
			
		||||
import org.schabi.newpipe.extractor.search.SearchResult;
 | 
			
		||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
 | 
			
		||||
import org.schabi.newpipe.extractor.search.SearchInfo;
 | 
			
		||||
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
 | 
			
		||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
 | 
			
		||||
import org.schabi.newpipe.report.ErrorActivity;
 | 
			
		||||
import org.schabi.newpipe.report.UserAction;
 | 
			
		||||
@@ -50,7 +49,6 @@ import java.util.List;
 | 
			
		||||
 | 
			
		||||
import io.reactivex.Maybe;
 | 
			
		||||
import io.reactivex.Single;
 | 
			
		||||
import io.reactivex.annotations.NonNull;
 | 
			
		||||
 | 
			
		||||
public final class ExtractorHelper {
 | 
			
		||||
    private static final String TAG = ExtractorHelper.class.getSimpleName();
 | 
			
		||||
@@ -66,29 +64,35 @@ public final class ExtractorHelper {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Single<SearchResult> searchFor(final int serviceId,
 | 
			
		||||
                                                 final String query,
 | 
			
		||||
                                                 final int pageNumber,
 | 
			
		||||
                                                 final String contentCountry,
 | 
			
		||||
                                                 final SearchEngine.Filter filter) {
 | 
			
		||||
    public static Single<SearchInfo> searchFor(final int serviceId,
 | 
			
		||||
                                               final String searchString,
 | 
			
		||||
                                               final List<String> contentFilter,
 | 
			
		||||
                                               final String sortFilter,
 | 
			
		||||
                                               final String contentCountry) {
 | 
			
		||||
        checkServiceId(serviceId);
 | 
			
		||||
        return Single.fromCallable(() ->
 | 
			
		||||
            SearchResult.getSearchResult(NewPipe.getService(serviceId).getSearchEngine(),
 | 
			
		||||
                    query, pageNumber, contentCountry, filter)
 | 
			
		||||
        );
 | 
			
		||||
            SearchInfo.getInfo(NewPipe.getService(serviceId),
 | 
			
		||||
                    NewPipe.getService(serviceId)
 | 
			
		||||
                        .getSearchQIHFactory()
 | 
			
		||||
                        .fromQuery(searchString, contentFilter, sortFilter),
 | 
			
		||||
                    contentCountry));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Single<InfoItemsPage> getMoreSearchItems(final int serviceId,
 | 
			
		||||
                                                             final String query,
 | 
			
		||||
                                                             final int nextPageNumber,
 | 
			
		||||
                                                             final String searchLanguage,
 | 
			
		||||
                                                             final SearchEngine.Filter filter) {
 | 
			
		||||
                                                           final String searchString,
 | 
			
		||||
                                                           final List<String> contentFilter,
 | 
			
		||||
                                                           final String sortFilter,
 | 
			
		||||
                                                           final String pageUrl,
 | 
			
		||||
                                                           final String contentCountry) {
 | 
			
		||||
        checkServiceId(serviceId);
 | 
			
		||||
        return searchFor(serviceId, query, nextPageNumber, searchLanguage, filter)
 | 
			
		||||
                .map((@NonNull SearchResult searchResult) ->
 | 
			
		||||
                        new InfoItemsPage(searchResult.resultList,
 | 
			
		||||
                                nextPageNumber + "",
 | 
			
		||||
                                searchResult.errors));
 | 
			
		||||
        return Single.fromCallable(() ->
 | 
			
		||||
                SearchInfo.getMoreItems(NewPipe.getService(serviceId),
 | 
			
		||||
                        NewPipe.getService(serviceId)
 | 
			
		||||
                            .getSearchQIHFactory()
 | 
			
		||||
                            .fromQuery(searchString, contentFilter, sortFilter),
 | 
			
		||||
                        contentCountry,
 | 
			
		||||
                        pageUrl));
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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));
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -26,10 +26,13 @@ import org.schabi.newpipe.download.DownloadActivity;
 | 
			
		||||
import org.schabi.newpipe.extractor.NewPipe;
 | 
			
		||||
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.stream.AudioStream;
 | 
			
		||||
import org.schabi.newpipe.extractor.stream.Stream;
 | 
			
		||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
 | 
			
		||||
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.detail.VideoDetailFragment;
 | 
			
		||||
import org.schabi.newpipe.fragments.list.channel.ChannelFragment;
 | 
			
		||||
@@ -283,9 +286,11 @@ public class NavigationHelper {
 | 
			
		||||
        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)
 | 
			
		||||
                .replace(R.id.fragment_holder, SearchFragment.getInstance(serviceId, query))
 | 
			
		||||
                .replace(R.id.fragment_holder, SearchFragment.getInstance(serviceId, searchString))
 | 
			
		||||
                .addToBackStack(SEARCH_FRAGMENT_TAG)
 | 
			
		||||
                .commit();
 | 
			
		||||
    }
 | 
			
		||||
@@ -314,7 +319,11 @@ public class NavigationHelper {
 | 
			
		||||
                .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 = "";
 | 
			
		||||
        defaultTransaction(fragmentManager)
 | 
			
		||||
                .replace(R.id.fragment_holder, ChannelFragment.getInstance(serviceId, url, name))
 | 
			
		||||
@@ -322,7 +331,10 @@ public class NavigationHelper {
 | 
			
		||||
                .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 = "";
 | 
			
		||||
        defaultTransaction(fragmentManager)
 | 
			
		||||
                .replace(R.id.fragment_holder, PlaylistFragment.getInstance(serviceId, url, name))
 | 
			
		||||
@@ -370,10 +382,10 @@ public class NavigationHelper {
 | 
			
		||||
    // 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);
 | 
			
		||||
        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);
 | 
			
		||||
        context.startActivity(mIntent);
 | 
			
		||||
    }
 | 
			
		||||
@@ -467,7 +479,8 @@ public class NavigationHelper {
 | 
			
		||||
 | 
			
		||||
        switch (linkType) {
 | 
			
		||||
            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));
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ import android.preference.PreferenceManager;
 | 
			
		||||
import android.support.annotation.DrawableRes;
 | 
			
		||||
import android.support.annotation.StringRes;
 | 
			
		||||
 | 
			
		||||
import org.schabi.newpipe.BuildConfig;
 | 
			
		||||
import org.schabi.newpipe.R;
 | 
			
		||||
import org.schabi.newpipe.extractor.NewPipe;
 | 
			
		||||
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.
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -125,7 +125,12 @@
 | 
			
		||||
    <string name="error_report_title">Error report</string>
 | 
			
		||||
    <string name="all">All</string>
 | 
			
		||||
    <string name="channel">Channel</string>
 | 
			
		||||
    <string name="channels">Channels</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="later">Later</string>
 | 
			
		||||
    <string name="disabled">Disabled</string>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user