22
33import android .content .Context ;
44import android .graphics .Typeface ;
5+ import android .util .Log ;
6+ import android .view .KeyEvent ;
57import android .view .LayoutInflater ;
68import android .view .View ;
79import android .view .ViewGroup ;
1315import androidx .recyclerview .widget .RecyclerView ;
1416
1517import java .util .ArrayList ;
18+ import java .util .Collections ;
1619import java .util .List ;
1720
1821import de .yaacc .R ;
@@ -24,6 +27,7 @@ public class PlaylistItemAdapter extends RecyclerView.Adapter<PlaylistItemAdapte
2427 private final Context context ;
2528 private final Player player ;
2629 private RecyclerView listView ;
30+ private int selectedForMovePosition = -1 ; // -1 indicates no item is selected for move
2731
2832 public PlaylistItemAdapter (Context ctx , RecyclerView listView , Player player ) {
2933 super ();
@@ -64,30 +68,93 @@ public void onBindViewHolder(final PlaylistItemAdapter.ViewHolder holder, final
6468 if (player .isPlaying () && listPosition <= player .getCurrentItemIndex ()) {
6569 holder .dragIcon .setImageDrawable (ThemeHelper .tintDrawable (context .getResources ().getDrawable (R .drawable .ic_baseline_lock_32 , context .getTheme ()), context .getTheme ()));
6670 holder .deleteIcon .setVisibility (View .GONE );
71+ holder .dragIcon .setFocusable (false ); // Cannot move locked items
6772 } else {
6873 holder .dragIcon .setImageDrawable (ThemeHelper .tintDrawable (context .getResources ().getDrawable (R .drawable .ic_baseline_drag_indicator_32 , context .getTheme ()), context .getTheme ()));
6974 holder .deleteIcon .setVisibility (View .VISIBLE );
75+ holder .dragIcon .setFocusable (true );
7076 }
7177 holder .deleteIcon .setOnClickListener (l -> removeItem (listPosition ));
7278 if (player .isPlaying () && player .getCurrentItemIndex () == listPosition ) {
7379 holder .name .setTypeface (null , Typeface .BOLD );
7480 holder .name .setText (item .getTitle () + " ▶" );
81+ } else {
82+ holder .name .setTypeface (null , Typeface .NORMAL ); // Ensure non-playing items are not bold
7583 }
84+
85+ if (listPosition == selectedForMovePosition ) {
86+ // Highlight the selected item (e.g., change background color or add a border)
87+ Log .d (getClass ().getName (), "Item selected for keyboard move: " + item .getTitle ());
88+ holder .itemView .setBackgroundColor (context .getResources ().getColor (R .color .design_default_color_secondary ));
89+ } else {
90+ holder .itemView .setBackgroundColor (context .getResources ().getColor (android .R .color .transparent ));
91+ }
92+
93+ holder .dragIcon .setOnKeyListener ((v , keyCode , event ) -> {
94+ if (event .getAction () == KeyEvent .ACTION_DOWN ) {
95+ if (keyCode == KeyEvent .KEYCODE_DPAD_CENTER || keyCode == KeyEvent .KEYCODE_ENTER ) {
96+ if (selectedForMovePosition == holder .getAdapterPosition ()) { // Use holder.getAdapterPosition() for safety
97+ // Deselect item
98+ int previouslySelected = selectedForMovePosition ;
99+ selectedForMovePosition = -1 ;
100+ notifyItemChanged (previouslySelected ); // To remove highlight
101+ return true ;
102+ } else if (selectedForMovePosition == -1 && !(player .isPlaying () && holder .getAdapterPosition () <= player .getCurrentItemIndex ())) {
103+ // Select item for move
104+ selectedForMovePosition = holder .getAdapterPosition ();
105+ notifyItemChanged (selectedForMovePosition ); // To add highlight
106+ return true ;
107+ }
108+ } else if (selectedForMovePosition == holder .getAdapterPosition ()) {
109+ if (keyCode == KeyEvent .KEYCODE_DPAD_UP ) {
110+ moveItem (selectedForMovePosition , selectedForMovePosition - 1 );
111+ return true ;
112+ } else if (keyCode == KeyEvent .KEYCODE_DPAD_DOWN ) {
113+ moveItem (selectedForMovePosition , selectedForMovePosition + 1 );
114+ return true ;
115+ }
116+ }
117+ }
118+ return false ;
119+ });
76120 }
77121
78- private void removeItem (int listPosition ) {
79- if (player .getItems ().size () > listPosition && listPosition > 0 ) {
80- player .getItems ().remove (listPosition );
81- setItems (player .getItems (), listPosition );
122+ public boolean moveItem (int fromPosition , int toPosition ) {
123+ if (player .isPlaying () && (fromPosition <= player .getCurrentItemIndex () || toPosition <= player .getCurrentItemIndex ())) {
124+ return false ;
82125 }
126+ if (fromPosition < 0 || fromPosition >= items .size () || toPosition < 0 || toPosition >= items .size ()) {
127+ return false ;
128+ }
129+
130+ Collections .swap (player .getItems (), fromPosition , toPosition );
131+ Collections .swap (items , fromPosition , toPosition );
132+ notifyItemMoved (fromPosition , toPosition );
133+
134+ // Update selectedForMovePosition if the moved item was the one selected for keyboard move
135+ if (selectedForMovePosition == fromPosition ) {
136+ selectedForMovePosition = toPosition ;
137+ }
138+ // No notifyItemChanged(fromPosition) or notifyItemChanged(toPosition) here
139+
140+ if (listView != null ) {
141+ listView .scrollToPosition (toPosition );
142+ }
143+ return true ;
83144 }
84145
85- public void setItems (List <PlayableItem > items , int removedPosition ) {
86- this .items .clear ();
87- this .items .addAll (items );
88- notifyItemRemoved (removedPosition );
89- int itemChangedCount = this .items .size () - removedPosition ;
90- notifyItemRangeChanged (removedPosition , itemChangedCount );
146+
147+ private void removeItem (int listPosition ) {
148+ if (player .getItems ().size () > listPosition && listPosition >= 0 && !(player .isPlaying () && listPosition <= player .getCurrentItemIndex ())) {
149+ player .getItems ().remove (listPosition );
150+ // Update local items list to reflect removal before notifying adapter
151+ PlayableItem removedItem = items .remove (listPosition );
152+ notifyItemRemoved (listPosition );
153+ // notifyItemRangeChanged is important if item positions change relative to others
154+ if (listPosition < items .size ()) {
155+ notifyItemRangeChanged (listPosition , items .size () - listPosition );
156+ }
157+ }
91158 }
92159
93160 static class ViewHolder extends RecyclerView .ViewHolder {
@@ -99,6 +166,7 @@ static class ViewHolder extends RecyclerView.ViewHolder {
99166 public ViewHolder (@ NonNull View itemView ) {
100167 super (itemView );
101168 dragIcon = itemView .findViewById (R .id .playlistItemDragIcon );
169+ dragIcon .setFocusable (true ); // Make the drag icon focusable
102170 deleteIcon = itemView .findViewById (R .id .playlistItemDeleteIcon );
103171 name = itemView .findViewById (R .id .playlistItemName );
104172 }
0 commit comments