Skip to content

Commit 7e4ecf0

Browse files
author
Muril
committed
Add search functionality to playlist selection dialog
- Add search EditText with icon to filter playlists by name - Implement real-time filtering with TextWatcher - Add clear button that appears when text is entered - Search is case-insensitive and matches partial playlist names - Store complete playlist list for filtering operations Closes #13154
1 parent 56a0436 commit 7e4ecf0

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed

app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.DEFAULT_THUMBNAIL_ID;
44

55
import android.os.Bundle;
6+
import android.text.Editable;
7+
import android.text.TextWatcher;
68
import android.view.LayoutInflater;
79
import android.view.View;
810
import android.view.ViewGroup;
11+
import android.widget.EditText;
912
import android.widget.TextView;
1013
import android.widget.Toast;
1114

@@ -21,7 +24,10 @@
2124
import org.schabi.newpipe.local.LocalItemListAdapter;
2225
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
2326

27+
import java.util.ArrayList;
2428
import java.util.List;
29+
import java.util.Locale;
30+
import java.util.stream.Collectors;
2531

2632
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
2733
import io.reactivex.rxjava3.disposables.CompositeDisposable;
@@ -32,7 +38,10 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
3238
private RecyclerView playlistRecyclerView;
3339
private LocalItemListAdapter playlistAdapter;
3440
private TextView playlistDuplicateIndicator;
41+
private EditText playlistSearchEditText;
42+
private View playlistSearchClear;
3543

44+
private List<PlaylistDuplicatesEntry> allPlaylists = new ArrayList<>();
3645
private final CompositeDisposable playlistDisposables = new CompositeDisposable();
3746

3847
/**
@@ -82,6 +91,11 @@ public void onViewCreated(@NonNull final View view, @Nullable final Bundle saved
8291
final View newPlaylistButton = view.findViewById(R.id.newPlaylist);
8392
newPlaylistButton.setOnClickListener(ignored -> openCreatePlaylistDialog());
8493

94+
// Setup search functionality
95+
playlistSearchEditText = view.findViewById(R.id.playlist_search_edit_text);
96+
playlistSearchClear = view.findViewById(R.id.playlist_search_clear);
97+
setupSearch();
98+
8599
playlistDisposables.add(playlistManager
86100
.getPlaylistDuplicates(getStreamEntities().get(0).getUrl())
87101
.observeOn(AndroidSchedulers.mainThread())
@@ -103,12 +117,66 @@ public void onDestroyView() {
103117
playlistDisposables.clear();
104118
playlistRecyclerView = null;
105119
playlistAdapter = null;
120+
playlistSearchEditText = null;
121+
playlistSearchClear = null;
122+
allPlaylists.clear();
106123
}
107124

108125
/*//////////////////////////////////////////////////////////////////////////
109126
// Helper
110127
//////////////////////////////////////////////////////////////////////////*/
111128

129+
private void setupSearch() {
130+
if (playlistSearchEditText == null || playlistSearchClear == null) {
131+
return;
132+
}
133+
134+
playlistSearchEditText.addTextChangedListener(new TextWatcher() {
135+
@Override
136+
public void beforeTextChanged(final CharSequence s, final int start,
137+
final int count, final int after) {
138+
}
139+
140+
@Override
141+
public void onTextChanged(final CharSequence s, final int start,
142+
final int before, final int count) {
143+
}
144+
145+
@Override
146+
public void afterTextChanged(final Editable s) {
147+
final String query = s.toString();
148+
playlistSearchClear.setVisibility(
149+
query.isEmpty() ? View.GONE : View.VISIBLE);
150+
filterPlaylists(query);
151+
}
152+
});
153+
154+
playlistSearchClear.setOnClickListener(v -> {
155+
playlistSearchEditText.setText("");
156+
playlistSearchClear.setVisibility(View.GONE);
157+
});
158+
}
159+
160+
private void filterPlaylists(final String query) {
161+
if (playlistAdapter == null || allPlaylists.isEmpty()) {
162+
return;
163+
}
164+
165+
if (query.isEmpty()) {
166+
playlistAdapter.clearStreamItemList();
167+
playlistAdapter.addItems(allPlaylists);
168+
} else {
169+
final String lowerCaseQuery = query.toLowerCase(Locale.getDefault());
170+
final List<PlaylistDuplicatesEntry> filteredPlaylists = allPlaylists.stream()
171+
.filter(playlist -> playlist.name.toLowerCase(Locale.getDefault())
172+
.contains(lowerCaseQuery))
173+
.collect(Collectors.toList());
174+
175+
playlistAdapter.clearStreamItemList();
176+
playlistAdapter.addItems(filteredPlaylists);
177+
}
178+
}
179+
112180
/** Display create playlist dialog. */
113181
public void openCreatePlaylistDialog() {
114182
if (getStreamEntities() == null || !isAdded()) {
@@ -129,6 +197,7 @@ private void onPlaylistsReceived(@NonNull final List<PlaylistDuplicatesEntry> pl
129197
if (playlistAdapter != null
130198
&& playlistRecyclerView != null
131199
&& playlistDuplicateIndicator != null) {
200+
allPlaylists = playlists;
132201
playlistAdapter.clearStreamItemList();
133202
playlistAdapter.addItems(playlists);
134203
playlistRecyclerView.setVisibility(View.VISIBLE);

app/src/main/res/layout/dialog_playlists.xml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,66 @@
33
android:layout_width="match_parent"
44
android:layout_height="match_parent">
55

6+
<FrameLayout
7+
android:id="@+id/playlist_search_container"
8+
android:layout_width="match_parent"
9+
android:layout_height="wrap_content"
10+
android:layout_marginStart="12dp"
11+
android:layout_marginTop="8dp"
12+
android:layout_marginEnd="12dp"
13+
android:layout_marginBottom="8dp"
14+
android:background="?attr/rounded_rectangle_background">
15+
16+
<org.schabi.newpipe.views.NewPipeEditText
17+
android:id="@+id/playlist_search_edit_text"
18+
android:layout_width="match_parent"
19+
android:layout_height="wrap_content"
20+
android:layout_gravity="center_vertical"
21+
android:background="@null"
22+
android:drawableStart="@drawable/ic_search"
23+
android:drawablePadding="8dp"
24+
android:focusable="true"
25+
android:focusableInTouchMode="true"
26+
android:hint="@string/search_playlists"
27+
android:imeOptions="actionSearch|flagNoFullscreen"
28+
android:inputType="textFilter|textNoSuggestions"
29+
android:maxLines="1"
30+
android:paddingStart="12dp"
31+
android:paddingTop="12dp"
32+
android:paddingEnd="48dp"
33+
android:paddingBottom="12dp"
34+
android:textSize="15sp" />
35+
36+
<FrameLayout
37+
android:id="@+id/playlist_search_clear"
38+
android:layout_width="48dp"
39+
android:layout_height="48dp"
40+
android:layout_gravity="end|center_vertical"
41+
android:contentDescription="@string/clear"
42+
android:focusable="true"
43+
android:visibility="gone">
44+
45+
<View
46+
android:layout_width="28dp"
47+
android:layout_height="28dp"
48+
android:layout_gravity="center"
49+
android:background="?attr/selectableItemBackgroundBorderless" />
50+
51+
<ImageView
52+
android:layout_width="24dp"
53+
android:layout_height="24dp"
54+
android:layout_gravity="center"
55+
android:contentDescription="@string/clear"
56+
android:scaleType="fitCenter"
57+
android:src="@drawable/ic_close" />
58+
</FrameLayout>
59+
</FrameLayout>
60+
661
<RelativeLayout
762
android:id="@+id/newPlaylist"
863
android:layout_width="wrap_content"
964
android:layout_height="wrap_content"
65+
android:layout_below="@+id/playlist_search_container"
1066
android:background="?attr/selectableItemBackground"
1167
android:clickable="true"
1268
android:focusable="true">

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@
456456
<string name="preferred_player_fetcher_notification_title">Getting info…</string>
457457
<string name="preferred_player_fetcher_notification_message">"Loading requested content"</string>
458458
<!-- Local Playlist -->
459+
<string name="search_playlists">Search playlists</string>
459460
<string name="create_playlist">New Playlist</string>
460461
<string name="duplicate_in_playlist">The playlists that are grayed out already contain this item.</string>
461462
<string name="rename_playlist">Rename</string>

0 commit comments

Comments
 (0)