Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve search suggestion experience when remote ones can't be fetched #4029

Merged
merged 2 commits into from
Sep 19, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.ExceptionUtils;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ServiceHelper;
Expand All @@ -78,7 +79,7 @@
import static java.util.Arrays.asList;
import static org.schabi.newpipe.util.AnimationUtils.animateView;

public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.InfoItemsPage>
public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.InfoItemsPage<?>>
implements BackPressable {
/*//////////////////////////////////////////////////////////////////////////
// Search
Expand Down Expand Up @@ -133,7 +134,6 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
private Map<Integer, String> menuItemToFilterName;
private StreamingService service;
private Page nextPage;
private String contentCountry;
private boolean isSuggestionsEnabled = true;

private Disposable searchDisposable;
Expand All @@ -154,6 +154,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
private TextView correctSuggestion;

private View suggestionsPanel;
private boolean suggestionsPanelVisible = false;
private RecyclerView suggestionsRecyclerView;

/*////////////////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -204,8 +205,6 @@ public void onCreate(final Bundle savedInstanceState) {
= PreferenceManager.getDefaultSharedPreferences(activity);
isSuggestionsEnabled = preferences
.getBoolean(getString(R.string.show_search_suggestions_key), true);
contentCountry = preferences.getString(getString(R.string.content_country_key),
getString(R.string.default_localization_key));
}

@Override
Expand Down Expand Up @@ -233,9 +232,7 @@ public void onPause() {
if (suggestionDisposable != null) {
suggestionDisposable.dispose();
}
if (disposables != null) {
disposables.clear();
}
disposables.clear();
hideKeyboardSearch();
}

Expand All @@ -249,8 +246,8 @@ public void onResume() {
try {
service = NewPipe.getService(serviceId);
} catch (final Exception e) {
ErrorActivity.reportError(getActivity(), e, getActivity().getClass(),
getActivity().findViewById(android.R.id.content),
ErrorActivity.reportError(getActivity(), e, requireActivity().getClass(),
requireActivity().findViewById(android.R.id.content),
ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
"",
"", R.string.general_error));
Expand Down Expand Up @@ -303,26 +300,20 @@ public void onDestroy() {
if (suggestionDisposable != null) {
suggestionDisposable.dispose();
}
if (disposables != null) {
disposables.clear();
}
disposables.clear();
}

@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case ReCaptchaActivity.RECAPTCHA_REQUEST:
if (resultCode == Activity.RESULT_OK
&& !TextUtils.isEmpty(searchString)) {
search(searchString, contentFilter, sortFilter);
} else {
Log.e(TAG, "ReCaptcha failed");
}
break;

default:
Log.e(TAG, "Request code from activity not supported [" + requestCode + "]");
break;
if (requestCode == ReCaptchaActivity.RECAPTCHA_REQUEST) {
if (resultCode == Activity.RESULT_OK
&& !TextUtils.isEmpty(searchString)) {
search(searchString, contentFilter, sortFilter);
} else {
Log.e(TAG, "ReCaptcha failed");
}
} else {
Log.e(TAG, "Request code from activity not supported [" + requestCode + "]");
}
}

Expand All @@ -340,7 +331,7 @@ protected void initViews(final View rootView, final Bundle savedInstanceState) {
@Override
public int getMovementFlags(@NonNull final RecyclerView recyclerView,
@NonNull final RecyclerView.ViewHolder viewHolder) {
return getSuggestionMovementFlags(recyclerView, viewHolder);
return getSuggestionMovementFlags(viewHolder);
}

@Override
Expand All @@ -352,7 +343,7 @@ public boolean onMove(@NonNull final RecyclerView recyclerView,

@Override
public void onSwiped(@NonNull final RecyclerView.ViewHolder viewHolder, final int i) {
onSuggestionItemSwiped(viewHolder, i);
onSuggestionItemSwiped(viewHolder);
}
}).attachToRecyclerView(suggestionsRecyclerView);

Expand Down Expand Up @@ -627,13 +618,15 @@ private void showSuggestionsPanel() {
if (DEBUG) {
Log.d(TAG, "showSuggestionsPanel() called");
}
suggestionsPanelVisible = true;
animateView(suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA, true, 200);
}

private void hideSuggestionsPanel() {
if (DEBUG) {
Log.d(TAG, "hideSuggestionsPanel() called");
}
suggestionsPanelVisible = false;
animateView(suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA, false, 200);
}

Expand Down Expand Up @@ -669,8 +662,7 @@ private void hideKeyboardSearch() {
}

private void showDeleteSuggestionDialog(final SuggestionItem item) {
if (activity == null || historyRecordManager == null || suggestionPublisher == null
|| searchEditText == null || disposables == null) {
if (activity == null || historyRecordManager == null || searchEditText == null) {
return;
}
final String query = item.query;
Expand All @@ -695,7 +687,7 @@ private void showDeleteSuggestionDialog(final SuggestionItem item) {

@Override
public boolean onBackPressed() {
if (suggestionsPanel.getVisibility() == View.VISIBLE
if (suggestionsPanelVisible
&& infoListAdapter.getItemsList().size() > 0
&& !isLoading.get()) {
hideSuggestionsPanel();
Expand Down Expand Up @@ -742,6 +734,13 @@ private void initSuggestionObserver() {

final Observable<List<SuggestionItem>> network = ExtractorHelper
.suggestionsFor(serviceId, query)
.onErrorReturn(throwable -> {
if (!ExceptionUtils.isNetworkRelated(throwable)) {
showSnackBarError(throwable, UserAction.GET_SUGGESTIONS,
NewPipe.getNameOfService(serviceId), searchString, 0);
}
return new ArrayList<>();
})
.toObservable()
.map(strings -> {
final List<SuggestionItem> result = new ArrayList<>();
Expand Down Expand Up @@ -791,21 +790,23 @@ protected void doInitialLoadLogic() {
// no-op
}

private void search(final String ss, final String[] cf, final String sf) {
private void search(final String theSearchString,
final String[] theContentFilter,
final String theSortFilter) {
if (DEBUG) {
Log.d(TAG, "search() called with: query = [" + ss + "]");
Log.d(TAG, "search() called with: query = [" + theSearchString + "]");
}
if (ss.isEmpty()) {
if (theSearchString.isEmpty()) {
return;
}

try {
final StreamingService streamingService = NewPipe.getServiceByUrl(ss);
final StreamingService streamingService = NewPipe.getServiceByUrl(theSearchString);
if (streamingService != null) {
showLoading();
disposables.add(Observable
.fromCallable(() ->
NavigationHelper.getIntentByLink(activity, streamingService, ss))
.fromCallable(() -> NavigationHelper.getIntentByLink(activity,
streamingService, theSearchString))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(intent -> {
Expand All @@ -820,29 +821,27 @@ private void search(final String ss, final String[] cf, final String sf) {
}

lastSearchedString = this.searchString;
this.searchString = ss;
this.searchString = theSearchString;
infoListAdapter.clearStreamItemList();
hideSuggestionsPanel();
hideKeyboardSearch();

historyRecordManager.onSearched(serviceId, ss)
disposables.add(historyRecordManager.onSearched(serviceId, theSearchString)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
ignored -> {
},
error -> showSnackBarError(error, UserAction.SEARCHED,
NewPipe.getNameOfService(serviceId), ss, 0)
);
suggestionPublisher.onNext(ss);
NewPipe.getNameOfService(serviceId), theSearchString, 0)
));
suggestionPublisher.onNext(theSearchString);
startLoading(false);
}

@Override
public void startLoading(final boolean forceLoad) {
super.startLoading(forceLoad);
if (disposables != null) {
disposables.clear();
}
disposables.clear();
if (searchDisposable != null) {
searchDisposable.dispose();
}
Expand Down Expand Up @@ -881,8 +880,7 @@ protected void loadMoreItems() {

@Override
protected boolean hasMoreItems() {
// TODO: No way to tell if search has more items in the moment
return true;
return Page.isValid(nextPage);
}

@Override
Expand All @@ -895,22 +893,25 @@ protected void onItemSelected(final InfoItem selectedItem) {
// Utils
//////////////////////////////////////////////////////////////////////////*/

private void changeContentFilter(final MenuItem item, final List<String> cf) {
this.filterItemCheckedId = item.getItemId();
private void changeContentFilter(final MenuItem item, final List<String> theContentFilter) {
filterItemCheckedId = item.getItemId();
item.setChecked(true);

this.contentFilter = new String[]{cf.get(0)};
contentFilter = new String[]{theContentFilter.get(0)};

if (!TextUtils.isEmpty(searchString)) {
search(searchString, this.contentFilter, sortFilter);
search(searchString, contentFilter, sortFilter);
}
}

private void setQuery(final int sid, final String ss, final String[] cf, final String sf) {
this.serviceId = sid;
this.searchString = searchString;
this.contentFilter = cf;
this.sortFilter = sf;
private void setQuery(final int theServiceId,
final String theSearchString,
final String[] theContentFilter,
final String theSortFilter) {
serviceId = theServiceId;
searchString = theSearchString;
contentFilter = theContentFilter;
sortFilter = theSortFilter;
}

/*//////////////////////////////////////////////////////////////////////////
Expand All @@ -924,7 +925,7 @@ public void handleSuggestions(@NonNull final List<SuggestionItem> suggestions) {
suggestionsRecyclerView.smoothScrollToPosition(0);
suggestionsRecyclerView.post(() -> suggestionListAdapter.setItems(suggestions));

if (errorPanelRoot.getVisibility() == View.VISIBLE) {
if (suggestionsPanelVisible && errorPanelRoot.getVisibility() == View.VISIBLE) {
hideLoading();
}
}
Expand Down Expand Up @@ -1027,7 +1028,7 @@ private void handleSearchSuggestion() {
}

@Override
public void handleNextItems(final ListExtractor.InfoItemsPage result) {
public void handleNextItems(final ListExtractor.InfoItemsPage<?> result) {
showListFooter(false);
infoListAdapter.addInfoItemList(result.getItems());
nextPage = result.getNextPage();
Expand Down Expand Up @@ -1066,8 +1067,7 @@ protected boolean onError(final Throwable exception) {
// Suggestion item touch helper
//////////////////////////////////////////////////////////////////////////*/

public int getSuggestionMovementFlags(@NonNull final RecyclerView recyclerView,
@NonNull final RecyclerView.ViewHolder viewHolder) {
public int getSuggestionMovementFlags(@NonNull final RecyclerView.ViewHolder viewHolder) {
final int position = viewHolder.getAdapterPosition();
if (position == RecyclerView.NO_POSITION) {
return 0;
Expand All @@ -1078,8 +1078,7 @@ public int getSuggestionMovementFlags(@NonNull final RecyclerView recyclerView,
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) : 0;
}

public void onSuggestionItemSwiped(@NonNull final RecyclerView.ViewHolder viewHolder,
final int i) {
public void onSuggestionItemSwiped(@NonNull final RecyclerView.ViewHolder viewHolder) {
final int position = viewHolder.getAdapterPosition();
final String query = suggestionListAdapter.getItem(position).query;
final Disposable onDelete = historyRecordManager.deleteSearchHistory(query)
Expand Down