mirror of
https://github.com/TeamNewPipe/NewPipe.git
synced 2025-10-03 09:49:21 +02:00
Display fragment based on search text
Keep Main Fragment until user's input
This commit is contained in:
parent
276bf390b2
commit
e8c3892c7d
5 changed files with 165 additions and 37 deletions
|
@ -764,14 +764,14 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
|
||||
if (showLocalSuggestions && shallShowRemoteSuggestionsNow) {
|
||||
return Observable.zip(
|
||||
getLocalSuggestionsObservable(query, 3),
|
||||
getRemoteSuggestionsObservable(query),
|
||||
(local, remote) -> {
|
||||
remote.removeIf(remoteItem -> local.stream().anyMatch(
|
||||
localItem -> localItem.equals(remoteItem)));
|
||||
local.addAll(remote);
|
||||
return local;
|
||||
})
|
||||
getLocalSuggestionsObservable(query, 3),
|
||||
getRemoteSuggestionsObservable(query),
|
||||
(local, remote) -> {
|
||||
remote.removeIf(remoteItem -> local.stream().anyMatch(
|
||||
localItem -> localItem.equals(remoteItem)));
|
||||
local.addAll(remote);
|
||||
return local;
|
||||
})
|
||||
.materialize();
|
||||
} else if (showLocalSuggestions) {
|
||||
return getLocalSuggestionsObservable(query, 25)
|
||||
|
@ -876,9 +876,9 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
searchDisposable.dispose();
|
||||
}
|
||||
searchDisposable = ExtractorHelper.searchFor(serviceId,
|
||||
searchString,
|
||||
Arrays.asList(contentFilter),
|
||||
sortFilter)
|
||||
searchString,
|
||||
Arrays.asList(contentFilter),
|
||||
sortFilter)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnEvent((searchResult, throwable) -> isLoading.set(false))
|
||||
|
@ -897,11 +897,11 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
searchDisposable.dispose();
|
||||
}
|
||||
searchDisposable = ExtractorHelper.getMoreSearchItems(
|
||||
serviceId,
|
||||
searchString,
|
||||
asList(contentFilter),
|
||||
sortFilter,
|
||||
nextPage)
|
||||
serviceId,
|
||||
searchString,
|
||||
asList(contentFilter),
|
||||
sortFilter,
|
||||
nextPage)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnEvent((nextItemsResult, throwable) -> isLoading.set(false))
|
||||
|
|
|
@ -22,7 +22,6 @@ import androidx.preference.Preference;
|
|||
import androidx.preference.PreferenceFragmentCompat;
|
||||
|
||||
import com.evernote.android.state.State;
|
||||
import com.jakewharton.rxbinding4.widget.RxTextView;
|
||||
import com.livefront.bridge.Bridge;
|
||||
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
|
@ -43,6 +42,10 @@ import org.schabi.newpipe.views.FocusOverlayView;
|
|||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
|
||||
import com.jakewharton.rxbinding4.widget.RxTextView;
|
||||
|
||||
/*
|
||||
* Created by Christian Schabesberger on 31.08.15.
|
||||
*
|
||||
|
@ -86,6 +89,8 @@ public class SettingsActivity extends AppCompatActivity implements
|
|||
@State
|
||||
boolean wasSearchActive;
|
||||
|
||||
private Disposable searchDisposable;
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceBundle) {
|
||||
setTheme(ThemeHelper.getSettingsThemeStyle(this));
|
||||
|
@ -111,9 +116,7 @@ public class SettingsActivity extends AppCompatActivity implements
|
|||
}
|
||||
}
|
||||
} else {
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.settings_fragment_holder, new MainSettingsFragment())
|
||||
.commit();
|
||||
showMainSettingsFragment();
|
||||
}
|
||||
|
||||
if (DeviceUtils.isTv(this)) {
|
||||
|
@ -189,8 +192,18 @@ public class SettingsActivity extends AppCompatActivity implements
|
|||
.commit();
|
||||
}
|
||||
|
||||
private void showMainSettingsFragment() {
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.settings_fragment_holder, new MainSettingsFragment())
|
||||
.commit();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (searchDisposable != null && !searchDisposable.isDisposed()) {
|
||||
searchDisposable.dispose();
|
||||
}
|
||||
setMenuSearchItem(null);
|
||||
searchFragment = null;
|
||||
super.onDestroy();
|
||||
|
@ -205,16 +218,43 @@ public class SettingsActivity extends AppCompatActivity implements
|
|||
final SettingsLayoutBinding settingsLayoutBinding,
|
||||
final boolean restored
|
||||
) {
|
||||
|
||||
searchContainer =
|
||||
settingsLayoutBinding.settingsToolbarLayout.toolbar
|
||||
.findViewById(R.id.toolbar_search_container);
|
||||
|
||||
// Configure input field for search
|
||||
searchEditText = searchContainer.findViewById(R.id.toolbar_search_edit_text);
|
||||
RxTextView.textChanges(searchEditText)
|
||||
searchDisposable = RxTextView.textChanges(searchEditText)
|
||||
// Ignore the initial empty state
|
||||
.skipInitialValue()
|
||||
// Wait some time after the last input before actually searching
|
||||
.debounce(200, TimeUnit.MILLISECONDS)
|
||||
.subscribe(v -> runOnUiThread(this::onSearchChanged));
|
||||
.subscribe(charSequence -> runOnUiThread(() -> {
|
||||
// Change Fragment based on search text
|
||||
if (charSequence.length() > 0) {
|
||||
if (searchFragment != null) {
|
||||
if (!searchFragment.isAdded()) {
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.settings_fragment_holder, searchFragment,
|
||||
PreferenceSearchFragment.NAME)
|
||||
.addToBackStack(PreferenceSearchFragment.NAME)
|
||||
.commit();
|
||||
} else {
|
||||
showSettingsFragment(searchFragment);
|
||||
}
|
||||
onSearchChanged();
|
||||
}
|
||||
} else {
|
||||
final Fragment current = getSupportFragmentManager()
|
||||
.findFragmentById(R.id.settings_fragment_holder);
|
||||
if (!(current instanceof MainSettingsFragment)) {
|
||||
getSupportFragmentManager()
|
||||
.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
showMainSettingsFragment();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// Configure clear button
|
||||
searchContainer.findViewById(R.id.toolbar_search_clear)
|
||||
|
@ -294,25 +334,36 @@ public class SettingsActivity extends AppCompatActivity implements
|
|||
Log.d(TAG, "setSearchActive called active=" + active);
|
||||
}
|
||||
|
||||
// Only reset the text when activating search from the toolbar
|
||||
if (active && !isSearchActive()) {
|
||||
resetSearchText();
|
||||
}
|
||||
|
||||
// Ignore if search is already in correct state
|
||||
if (isSearchActive() == active) {
|
||||
return;
|
||||
}
|
||||
|
||||
wasSearchActive = active;
|
||||
if (wasSearchActive) {
|
||||
searchEditText.post(() -> {
|
||||
searchEditText.requestFocus();
|
||||
KeyboardUtil.showKeyboard(this, searchEditText);
|
||||
});
|
||||
}
|
||||
|
||||
searchContainer.setVisibility(active ? View.VISIBLE : View.GONE);
|
||||
if (menuSearchItem != null) {
|
||||
menuSearchItem.setVisible(!active);
|
||||
}
|
||||
|
||||
if (active) {
|
||||
getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(FRAGMENT_HOLDER_ID, searchFragment, PreferenceSearchFragment.NAME)
|
||||
.addToBackStack(PreferenceSearchFragment.NAME)
|
||||
.commit();
|
||||
|
||||
if (active && searchText == null) {
|
||||
showMainSettingsFragment();
|
||||
} else if (active) {
|
||||
// Only add if not already added
|
||||
if (!searchFragment.isAdded()) {
|
||||
showSettingsFragment(searchFragment);
|
||||
}
|
||||
KeyboardUtil.showKeyboard(this, searchEditText);
|
||||
} else if (searchFragment != null) {
|
||||
hideSearchFragment();
|
||||
|
@ -323,8 +374,6 @@ public class SettingsActivity extends AppCompatActivity implements
|
|||
|
||||
KeyboardUtil.hideKeyboard(this, searchEditText);
|
||||
}
|
||||
|
||||
resetSearchText();
|
||||
}
|
||||
|
||||
private void hideSearchFragment() {
|
||||
|
@ -388,5 +437,18 @@ public class SettingsActivity extends AppCompatActivity implements
|
|||
}
|
||||
}
|
||||
|
||||
// Functions needed for testing
|
||||
protected EditText getSearchEditText() {
|
||||
return searchEditText;
|
||||
}
|
||||
|
||||
public void setMockEditText(final EditText editText) {
|
||||
this.searchEditText = editText;
|
||||
}
|
||||
|
||||
protected static int getFragmentHolderId() {
|
||||
return FRAGMENT_HOLDER_ID;
|
||||
}
|
||||
|
||||
//endregion
|
||||
}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package org.schabi.newpipe.settings.preferencesearch;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -21,9 +18,6 @@ public class PreferenceSearcher {
|
|||
}
|
||||
|
||||
List<PreferenceSearchItem> searchFor(final String keyword) {
|
||||
if (TextUtils.isEmpty(keyword)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return configuration.getSearcher()
|
||||
.search(allEntries.stream(), keyword)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:clickable="true"
|
||||
android:visibility="gone"
|
||||
tools:visibility="gone">
|
||||
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package org.schabi.newpipe.settings;
|
||||
|
||||
import android.widget.EditText;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchFragment;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class SettingsActivityTest {
|
||||
|
||||
private SettingsActivity activity;
|
||||
private FragmentManager fragmentManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
activity = Mockito.spy(new SettingsActivity());
|
||||
fragmentManager = Mockito.mock(FragmentManager.class);
|
||||
Mockito.doReturn(fragmentManager).when(activity).getSupportFragmentManager();
|
||||
// Mock the searchEditText
|
||||
final EditText editText = Mockito.mock(EditText.class);
|
||||
activity.setMockEditText(editText);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mainSettingsFragmentDisplayedWhenSearchInactive() {
|
||||
when(fragmentManager.findFragmentById(anyInt()))
|
||||
.thenReturn(new MainSettingsFragment());
|
||||
|
||||
activity.setSearchActive(false);
|
||||
|
||||
final Fragment fragment = activity.getSupportFragmentManager()
|
||||
.findFragmentById(SettingsActivity.getFragmentHolderId());
|
||||
assertTrue(fragment instanceof MainSettingsFragment);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preferenceSearchFragmentDisplayedWhenSearchActiveAndTextNotEmpty() {
|
||||
when(fragmentManager.findFragmentById(anyInt()))
|
||||
.thenReturn(new PreferenceSearchFragment());
|
||||
|
||||
activity.setSearchActive(true);
|
||||
Mockito.when(activity.getSearchEditText().getText())
|
||||
.thenReturn(new android.text.SpannableStringBuilder("query"));
|
||||
|
||||
final Fragment fragment = activity.getSupportFragmentManager()
|
||||
.findFragmentById(SettingsActivity.getFragmentHolderId());
|
||||
assertTrue(fragment instanceof PreferenceSearchFragment);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mainSettingsFragmentDisplayedWhenSearchActiveButTextEmpty() {
|
||||
when(fragmentManager.findFragmentById(anyInt()))
|
||||
.thenReturn(new MainSettingsFragment());
|
||||
|
||||
activity.setSearchActive(true);
|
||||
Mockito.when(activity.getSearchEditText().getText())
|
||||
.thenReturn(new android.text.SpannableStringBuilder(""));
|
||||
|
||||
final Fragment fragment = activity.getSupportFragmentManager()
|
||||
.findFragmentById(SettingsActivity.getFragmentHolderId());
|
||||
assertTrue(fragment instanceof MainSettingsFragment);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue