From 7edb1f59413ff69bba3608be98f177ec47e945b2 Mon Sep 17 00:00:00 2001 From: Me7c7 Date: Sun, 1 Dec 2024 11:17:45 +0200 Subject: [PATCH] Huawei: Added selecting for more than one item for music management --- .../musicmanager/MusicManagerActivity.java | 126 +++++++++++++++--- .../adapter/MusicListAdapter.java | 55 ++++++-- app/src/main/res/drawable/ic_music_item.xml | 5 + .../main/res/layout/activity_musicmanager.xml | 107 +++++++++++---- .../res/layout/item_musicmanager_song.xml | 2 +- app/src/main/res/values/strings.xml | 2 + 6 files changed, 242 insertions(+), 55 deletions(-) create mode 100644 app/src/main/res/drawable/ic_music_item.xml diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/musicmanager/MusicManagerActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/musicmanager/MusicManagerActivity.java index cc7f821f9..b6999f969 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/musicmanager/MusicManagerActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/musicmanager/MusicManagerActivity.java @@ -31,6 +31,7 @@ import androidx.annotation.NonNull; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.floatingactionbutton.FloatingActionButton; @@ -80,6 +81,12 @@ public class MusicManagerActivity extends AbstractGBActivity { private FloatingActionButton fabMusicUpload; private FloatingActionButton fabMusicPlaylistAdd; + + private MaterialToolbar bottomToolbar; + private TextView selectionInfo; + private ImageButton selectionAddPlaylist; + private ImageButton selectionDelete; + private int maxMusicCount = 0; private int maxPlaylistCount = 0; @@ -134,6 +141,14 @@ public class MusicManagerActivity extends AbstractGBActivity { hideActionButtons(); + bottomToolbar = findViewById(R.id.bottom_toolbar); + + ImageButton cancelSelection = findViewById(R.id.music_cancel_selection); + selectionInfo = findViewById(R.id.music_selection_info); + selectionAddPlaylist = findViewById(R.id.music_multiselect_add_to_playlist); + selectionDelete = findViewById(R.id.music_multiselect_delete); + + RecyclerView musicListView = findViewById(R.id.music_songs_list); loadingView = findViewById(R.id.music_loading); @@ -153,20 +168,56 @@ public class MusicManagerActivity extends AbstractGBActivity { musicAdapter = new MusicListAdapter( musicList, - new MusicListAdapter.onItemAction() { + new MusicListAdapter.onDataAction() { @Override public void onItemClick(View view, GBDeviceMusic music) { openPopupMenu(view, music); } @Override - public boolean onItemLongClick(View view, GBDeviceMusic music) { - return false; + public void onMultiSelect(int count, boolean limit) { + multiSelect(count, limit); } + } ); musicListView.setAdapter(musicAdapter); + cancelSelection.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + musicAdapter.clearSelectedItems(); + } + }); + + selectionAddPlaylist.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + List musics = musicAdapter.getSelectedItems(); + if(!musics.isEmpty()) { + ArrayList list = new ArrayList<>(); + for(GBDeviceMusic music: musics) { + list.add(music.getId()); + } + addMusicSongToPlaylist(list); + } + } + }); + + selectionDelete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + List musics = musicAdapter.getSelectedItems(); + if(!musics.isEmpty()) { + ArrayList list = new ArrayList<>(); + for(GBDeviceMusic music: musics) { + list.add(music.getId()); + } + deleteMusicMultipleConfirm(list); + } + } + }); + playlistSpinnerLayout = findViewById(R.id.music_playlists_layout); playlistsSpinner = findViewById(R.id.music_playlists); @@ -194,6 +245,7 @@ public class MusicManagerActivity extends AbstractGBActivity { @Override public void onItemSelected(AdapterView adapterView, View view, int i, long l) { GBDeviceMusicPlaylist item = (GBDeviceMusicPlaylist) adapterView.getItemAtPosition(i); + musicAdapter.clearSelectedItems(); if (item.getId() == 0) { deletePlaylist.setVisibility(View.GONE); renamePlaylist.setVisibility(View.GONE); @@ -218,6 +270,25 @@ public class MusicManagerActivity extends AbstractGBActivity { playlistsSpinner.setAdapter(playlistAdapter); } + private void multiSelect(int count, boolean limit) { + if(limit) { + GB.toast(this, R.string.music_multiselect_limit, Toast.LENGTH_LONG, GB.WARN); + } + if(count > 0) { + hideActionButtons(); + bottomToolbar.setVisibility(View.VISIBLE); + selectionInfo.setText("" + count); + if(playlists.size() <= 1) { + selectionAddPlaylist.setVisibility(View.GONE); + } else { + selectionAddPlaylist.setVisibility(View.VISIBLE); + } + } else { + bottomToolbar.setVisibility(View.GONE); + showActionButtons(); + } + } + private void hideActionButtons() { fabMusicUpload.hide(); fabMusicPlaylistAdd.hide(); @@ -246,6 +317,7 @@ public class MusicManagerActivity extends AbstractGBActivity { private void stopLoading() { loadingTimeout.removeCallbacks(loadingRunnable); loadingView.setVisibility(View.GONE); + musicAdapter.clearSelectedItems(); showActionButtons(); } @@ -311,7 +383,6 @@ public class MusicManagerActivity extends AbstractGBActivity { } GBDeviceMusicPlaylist current = (GBDeviceMusicPlaylist) playlistsSpinner.getSelectedItem(); - musicList.clear(); if (current.getId() == 0) { menu.removeItem(R.id.musicmanager_delete_from_playlist); } else { @@ -335,19 +406,36 @@ public class MusicManagerActivity extends AbstractGBActivity { deleteMusicConfirm(music); return true; } else if (itemId == R.id.musicmanager_add_to_playlist) { - addMusicSongToPlaylist(music); + ArrayList list = new ArrayList<>(); + list.add(music.getId()); + addMusicSongToPlaylist(list); return true; } return false; } private void deleteMusicConfirm(final GBDeviceMusic music) { + ArrayList list = new ArrayList<>(); + list.add(music.getId()); + new MaterialAlertDialogBuilder(this) .setTitle(R.string.Delete) .setMessage(this.getString(R.string.music_delete_confirm_description, music.getTitle())) .setIcon(R.drawable.ic_warning) .setPositiveButton(android.R.string.yes, (dialog, whichButton) -> { - deleteMusicFromDevice((GBDeviceMusicPlaylist) playlistsSpinner.getSelectedItem(), music); + deleteMusicFromDevice((GBDeviceMusicPlaylist) playlistsSpinner.getSelectedItem(), list); + }) + .setNegativeButton(android.R.string.no, null) + .show(); + } + + private void deleteMusicMultipleConfirm(final ArrayList list) { + new MaterialAlertDialogBuilder(this) + .setTitle(R.string.Delete) + .setMessage(this.getString(R.string.music_delete_multiple_confirm_description, list.size())) + .setIcon(R.drawable.ic_warning) + .setPositiveButton(android.R.string.yes, (dialog, whichButton) -> { + deleteMusicFromDevice((GBDeviceMusicPlaylist) playlistsSpinner.getSelectedItem(), list); }) .setNegativeButton(android.R.string.no, null) .show(); @@ -368,17 +456,13 @@ public class MusicManagerActivity extends AbstractGBActivity { GBApplication.deviceService(mGBDevice).onMusicOperation(2, playlist.getId(), newPlaylistName, null); } - private void addMusicToDevicePlaylist(GBDeviceMusicPlaylist playlist, final GBDeviceMusic music) { + private void addMusicToDevicePlaylist(GBDeviceMusicPlaylist playlist, final ArrayList list) { startLoading(); - ArrayList list = new ArrayList<>(); - list.add(music.getId()); GBApplication.deviceService(mGBDevice).onMusicOperation(3, playlist.getId(), null, list); } - private void deleteMusicFromDevice(GBDeviceMusicPlaylist playlist, final GBDeviceMusic music) { + private void deleteMusicFromDevice(GBDeviceMusicPlaylist playlist, final ArrayList list) { startLoading(); - ArrayList list = new ArrayList<>(); - list.add(music.getId()); GBApplication.deviceService(mGBDevice).onMusicOperation(4, playlist.getId(), null, list); } @@ -387,7 +471,7 @@ public class MusicManagerActivity extends AbstractGBActivity { input.setInputType(InputType.TYPE_CLASS_TEXT); FrameLayout container = new FrameLayout(this); - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.leftMargin = getResources().getDimensionPixelSize(R.dimen.dialog_margin); params.rightMargin = getResources().getDimensionPixelSize(R.dimen.dialog_margin); input.setLayoutParams(params); @@ -398,7 +482,9 @@ public class MusicManagerActivity extends AbstractGBActivity { .setView(container) .setPositiveButton(android.R.string.ok, (dialog, whichButton) -> { String playlistName = input.getText().toString(); - addPlaylistToDevice(playlistName); + if(!playlistName.isEmpty()) { + addPlaylistToDevice(playlistName); + } }) .setNegativeButton(android.R.string.cancel, null) .show(); @@ -423,7 +509,9 @@ public class MusicManagerActivity extends AbstractGBActivity { .setView(container) .setPositiveButton(android.R.string.ok, (dialog, whichButton) -> { String playlistName = input.getText().toString(); - renamePlaylistOnDevice(playlist, playlistName); + if(!playlistName.isEmpty()) { + renamePlaylistOnDevice(playlist, playlistName); + } }) .setNegativeButton(android.R.string.cancel, null) .show(); @@ -443,7 +531,7 @@ public class MusicManagerActivity extends AbstractGBActivity { .show(); } - private void addMusicSongToPlaylist(final GBDeviceMusic music) { + private void addMusicSongToPlaylist(final ArrayList list) { final Spinner dPlaylists = new Spinner(this); List dialogPlaylists = new ArrayList<>(); @@ -469,7 +557,7 @@ public class MusicManagerActivity extends AbstractGBActivity { .setView(container) .setPositiveButton(android.R.string.ok, (dialog, whichButton) -> { GBDeviceMusicPlaylist playlist = (GBDeviceMusicPlaylist) dPlaylists.getSelectedItem(); - addMusicToDevicePlaylist(playlist, music); + addMusicToDevicePlaylist(playlist, list); }) .setNegativeButton(android.R.string.cancel, null) .show(); @@ -513,7 +601,7 @@ public class MusicManagerActivity extends AbstractGBActivity { int playlistIndex = intent.getIntExtra("playlistIndex", -1); String playlistName = intent.getStringExtra("playlistName"); - if (playlistIndex != -1 && !TextUtils.isEmpty(playlistName)) { + if (playlistIndex != -1 && playlistName != null) { playlists.add(new GBDeviceMusicPlaylist(playlistIndex, playlistName, new ArrayList<>())); playlistAdapter.notifyDataSetChanged(); } @@ -531,7 +619,7 @@ public class MusicManagerActivity extends AbstractGBActivity { } else if (operation == 2) { int playlistIndex = intent.getIntExtra("playlistIndex", -1); String playlistName = intent.getStringExtra("playlistName"); - if (playlistIndex != -1 && !TextUtils.isEmpty(playlistName)) { + if (playlistIndex != -1 && playlistName != null) { for (GBDeviceMusicPlaylist playlist : playlists) { if (playlist.getId() == playlistIndex) { playlist.setName(playlistName); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/MusicListAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/MusicListAdapter.java index a661906b6..6b9580d4d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/MusicListAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/MusicListAdapter.java @@ -3,29 +3,30 @@ package nodomain.freeyourgadget.gadgetbridge.adapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import java.util.ArrayList; import java.util.List; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceMusic; public class MusicListAdapter extends RecyclerView.Adapter { - - public interface onItemAction { + + public static int MAX_MULTISELECT_COUNT = 50; + public interface onDataAction { void onItemClick(View view, GBDeviceMusic music); - boolean onItemLongClick(View view, GBDeviceMusic music); + void onMultiSelect(int count, boolean limit); } private final List musicList; - private final onItemAction callback; + private final onDataAction callback; - public MusicListAdapter(List list, onItemAction callback) { + private final List selectedItems = new ArrayList<>(); + + public MusicListAdapter(List list, onDataAction callback) { this.musicList = list; this.callback = callback; } @@ -46,6 +47,20 @@ public class MusicListAdapter extends RecyclerView.Adapter= MAX_MULTISELECT_COUNT) { + callback.onMultiSelect(selectedItems.size(), true); + return; + } + if(selectedItems.contains(music)) { + selectedItems.remove(music); + } else { + selectedItems.add(music); + } + notifyItemChanged(musicList.indexOf(music)); + callback.onMultiSelect(selectedItems.size(), false); + } + @Override public void onBindViewHolder(final MusicListAdapter.MusicViewHolder holder, int position) { final GBDeviceMusic music = musicList.get(position); @@ -53,32 +68,50 @@ public class MusicListAdapter extends RecyclerView.Adapter getSelectedItems() { + return selectedItems; } public static class MusicViewHolder extends RecyclerView.ViewHolder { final TextView musicArtist; final TextView musicTitle; + final ImageView icon; MusicViewHolder(View itemView) { super(itemView); musicArtist = itemView.findViewById(R.id.item_details); musicTitle = itemView.findViewById(R.id.item_name); + icon = itemView.findViewById(R.id.item_image); } } diff --git a/app/src/main/res/drawable/ic_music_item.xml b/app/src/main/res/drawable/ic_music_item.xml new file mode 100644 index 000000000..14e99a613 --- /dev/null +++ b/app/src/main/res/drawable/ic_music_item.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_musicmanager.xml b/app/src/main/res/layout/activity_musicmanager.xml index 9f8eeaa76..3749a27da 100644 --- a/app/src/main/res/layout/activity_musicmanager.xml +++ b/app/src/main/res/layout/activity_musicmanager.xml @@ -21,27 +21,29 @@ android:layout_below="@id/music_device_info" android:orientation="horizontal"> - - - + + + + + @@ -53,6 +55,7 @@ android:layout_centerHorizontal="true" android:divider="@null" /> + + android:contentDescription="@string/music_new_playlist" + app:srcCompat="@drawable/ic_add" /> + + + + + + + + + + + + + + + + + + + android:src="@drawable/ic_music_item"/> Manage Music Manage music on the watch Are you sure you want to delete \'%1$s\'? + Are you sure you want to delete \'%1$d\' songs? Add to playlist Delete from playlist Delete song @@ -3470,6 +3471,7 @@ Rename playlist Error occurred Supported formats: %1$s\nWatch storage: %2$d MB + Limit for selecting more than one item reached Welcome