1
0
Fork 0
mirror of https://github.com/TeamNewPipe/NewPipe.git synced 2025-10-03 17:59:41 +02:00

Display fragment based on search text

Keep Main Fragment until user's input
This commit is contained in:
VougJo23 2025-06-08 13:38:06 +03:00
parent 276bf390b2
commit e8c3892c7d
5 changed files with 165 additions and 37 deletions

View file

@ -22,7 +22,6 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import com.evernote.android.state.State; import com.evernote.android.state.State;
import com.jakewharton.rxbinding4.widget.RxTextView;
import com.livefront.bridge.Bridge; import com.livefront.bridge.Bridge;
import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.MainActivity;
@ -43,6 +42,10 @@ import org.schabi.newpipe.views.FocusOverlayView;
import java.util.concurrent.TimeUnit; 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. * Created by Christian Schabesberger on 31.08.15.
* *
@ -86,6 +89,8 @@ public class SettingsActivity extends AppCompatActivity implements
@State @State
boolean wasSearchActive; boolean wasSearchActive;
private Disposable searchDisposable;
@Override @Override
protected void onCreate(final Bundle savedInstanceBundle) { protected void onCreate(final Bundle savedInstanceBundle) {
setTheme(ThemeHelper.getSettingsThemeStyle(this)); setTheme(ThemeHelper.getSettingsThemeStyle(this));
@ -111,9 +116,7 @@ public class SettingsActivity extends AppCompatActivity implements
} }
} }
} else { } else {
getSupportFragmentManager().beginTransaction() showMainSettingsFragment();
.replace(R.id.settings_fragment_holder, new MainSettingsFragment())
.commit();
} }
if (DeviceUtils.isTv(this)) { if (DeviceUtils.isTv(this)) {
@ -189,8 +192,18 @@ public class SettingsActivity extends AppCompatActivity implements
.commit(); .commit();
} }
private void showMainSettingsFragment() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.settings_fragment_holder, new MainSettingsFragment())
.commit();
}
@Override @Override
protected void onDestroy() { protected void onDestroy() {
if (searchDisposable != null && !searchDisposable.isDisposed()) {
searchDisposable.dispose();
}
setMenuSearchItem(null); setMenuSearchItem(null);
searchFragment = null; searchFragment = null;
super.onDestroy(); super.onDestroy();
@ -205,16 +218,43 @@ public class SettingsActivity extends AppCompatActivity implements
final SettingsLayoutBinding settingsLayoutBinding, final SettingsLayoutBinding settingsLayoutBinding,
final boolean restored final boolean restored
) { ) {
searchContainer = searchContainer =
settingsLayoutBinding.settingsToolbarLayout.toolbar settingsLayoutBinding.settingsToolbarLayout.toolbar
.findViewById(R.id.toolbar_search_container); .findViewById(R.id.toolbar_search_container);
// Configure input field for search // Configure input field for search
searchEditText = searchContainer.findViewById(R.id.toolbar_search_edit_text); 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 // Wait some time after the last input before actually searching
.debounce(200, TimeUnit.MILLISECONDS) .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 // Configure clear button
searchContainer.findViewById(R.id.toolbar_search_clear) searchContainer.findViewById(R.id.toolbar_search_clear)
@ -294,25 +334,36 @@ public class SettingsActivity extends AppCompatActivity implements
Log.d(TAG, "setSearchActive called active=" + active); 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 // Ignore if search is already in correct state
if (isSearchActive() == active) { if (isSearchActive() == active) {
return; return;
} }
wasSearchActive = active; wasSearchActive = active;
if (wasSearchActive) {
searchEditText.post(() -> {
searchEditText.requestFocus();
KeyboardUtil.showKeyboard(this, searchEditText);
});
}
searchContainer.setVisibility(active ? View.VISIBLE : View.GONE); searchContainer.setVisibility(active ? View.VISIBLE : View.GONE);
if (menuSearchItem != null) { if (menuSearchItem != null) {
menuSearchItem.setVisible(!active); menuSearchItem.setVisible(!active);
} }
if (active) { if (active && searchText == null) {
getSupportFragmentManager() showMainSettingsFragment();
.beginTransaction() } else if (active) {
.add(FRAGMENT_HOLDER_ID, searchFragment, PreferenceSearchFragment.NAME) // Only add if not already added
.addToBackStack(PreferenceSearchFragment.NAME) if (!searchFragment.isAdded()) {
.commit(); showSettingsFragment(searchFragment);
}
KeyboardUtil.showKeyboard(this, searchEditText); KeyboardUtil.showKeyboard(this, searchEditText);
} else if (searchFragment != null) { } else if (searchFragment != null) {
hideSearchFragment(); hideSearchFragment();
@ -323,8 +374,6 @@ public class SettingsActivity extends AppCompatActivity implements
KeyboardUtil.hideKeyboard(this, searchEditText); KeyboardUtil.hideKeyboard(this, searchEditText);
} }
resetSearchText();
} }
private void hideSearchFragment() { 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 //endregion
} }

View file

@ -1,9 +1,6 @@
package org.schabi.newpipe.settings.preferencesearch; package org.schabi.newpipe.settings.preferencesearch;
import android.text.TextUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -21,9 +18,6 @@ public class PreferenceSearcher {
} }
List<PreferenceSearchItem> searchFor(final String keyword) { List<PreferenceSearchItem> searchFor(final String keyword) {
if (TextUtils.isEmpty(keyword)) {
return Collections.emptyList();
}
return configuration.getSearcher() return configuration.getSearcher()
.search(allEntries.stream(), keyword) .search(allEntries.stream(), keyword)

View file

@ -18,6 +18,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center" android:gravity="center"
android:orientation="vertical" android:orientation="vertical"
android:clickable="true"
android:visibility="gone" android:visibility="gone"
tools:visibility="gone"> tools:visibility="gone">

View file

@ -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);
}
}