diff --git a/app/src/main/java/com/cappielloantonio/tempo/interfaces/ClickCallback.java b/app/src/main/java/com/cappielloantonio/tempo/interfaces/ClickCallback.java index c87e7179..c4d26133 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/interfaces/ClickCallback.java +++ b/app/src/main/java/com/cappielloantonio/tempo/interfaces/ClickCallback.java @@ -29,4 +29,5 @@ public interface ClickCallback { default void onMusicFolderClick(Bundle bundle) {} default void onMusicDirectoryClick(Bundle bundle) {} default void onMusicIndexClick(Bundle bundle) {} + default void onDownloadGroupLongClick(Bundle bundle) {} } diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/DownloadHorizontalAdapter.java b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/DownloadHorizontalAdapter.java index 7183f6ce..1dedeeff 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/DownloadHorizontalAdapter.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/DownloadHorizontalAdapter.java @@ -191,7 +191,7 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter 0 && grouped.get(position - 1) != null && !Objects.equals(grouped.get(position - 1).getArtist(), grouped.get(position).getArtist())) { @@ -213,7 +213,7 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter filteredSongs = null; + switch (view) { + case Constants.DOWNLOAD_TYPE_ALBUM: + filteredSongs = filterSong(Constants.DOWNLOAD_TYPE_ALBUM, grouped.get(getBindingAdapterPosition()).getAlbumId(), songs); + break; + case Constants.DOWNLOAD_TYPE_ARTIST: + filteredSongs = filterSong(Constants.DOWNLOAD_TYPE_ARTIST, grouped.get(getBindingAdapterPosition()).getArtistId(), songs); + break; + case Constants.DOWNLOAD_TYPE_GENRE: + filteredSongs = filterSong(Constants.DOWNLOAD_TYPE_GENRE, grouped.get(getBindingAdapterPosition()).getGenre(), songs); + break; + case Constants.DOWNLOAD_TYPE_YEAR: + filteredSongs = filterSong(Constants.DOWNLOAD_TYPE_YEAR, grouped.get(getBindingAdapterPosition()).getYear().toString(), songs); + break; + } + + if (filteredSongs == null) { + return false; + } + + bundle.putParcelableArrayList(Constants.DOWNLOAD_TYPE_GROUP, new ArrayList<>(filteredSongs)); + bundle.putString(Constants.DOWNLOAD_TYPE_GROUP_NAME, item.downloadedItemTitleTextView.getText().toString()); + click.onDownloadGroupLongClick(bundle); + return true; } } } diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java index c0f7349c..83995d8a 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java @@ -254,4 +254,9 @@ public class DownloadFragment extends Fragment implements ClickCallback { public void onMediaLongClick(Bundle bundle) { Navigation.findNavController(requireView()).navigate(R.id.songBottomSheetDialog, bundle); } + + @Override + public void onDownloadGroupLongClick(Bundle bundle) { + Navigation.findNavController(requireView()).navigate(R.id.downloadBottomSheetDialog, bundle); + } } diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/bottomsheetdialog/DownloadedBottomSheetDialog.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/bottomsheetdialog/DownloadedBottomSheetDialog.java new file mode 100644 index 00000000..a98bdfdd --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/bottomsheetdialog/DownloadedBottomSheetDialog.java @@ -0,0 +1,133 @@ +package com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog; + +import android.content.ComponentName; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.media3.common.MediaItem; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.session.MediaBrowser; +import androidx.media3.session.SessionToken; + +import com.cappielloantonio.tempo.R; +import com.cappielloantonio.tempo.glide.CustomGlideRequest; +import com.cappielloantonio.tempo.model.Download; +import com.cappielloantonio.tempo.service.MediaManager; +import com.cappielloantonio.tempo.service.MediaService; +import com.cappielloantonio.tempo.subsonic.models.Child; +import com.cappielloantonio.tempo.ui.activity.MainActivity; +import com.cappielloantonio.tempo.util.Constants; +import com.cappielloantonio.tempo.util.DownloadUtil; +import com.cappielloantonio.tempo.util.MappingUtil; +import com.cappielloantonio.tempo.util.MusicUtil; +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; +import com.google.common.util.concurrent.ListenableFuture; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@UnstableApi +public class DownloadedBottomSheetDialog extends BottomSheetDialogFragment implements View.OnClickListener { + private List songs; + + private String groupName; + + private ListenableFuture mediaBrowserListenableFuture; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.bottom_sheet_downloaded_dialog, container, false); + + songs = this.requireArguments().getParcelableArrayList(Constants.DOWNLOAD_TYPE_GROUP); + groupName = this.requireArguments().getString(Constants.DOWNLOAD_TYPE_GROUP_NAME); + + init(view); + + return view; + } + + @Override + public void onStart() { + super.onStart(); + + initializeMediaBrowser(); + } + + @Override + public void onStop() { + releaseMediaBrowser(); + super.onStop(); + } + + private void init(View view) { + ImageView coverAlbum = view.findViewById(R.id.album_cover_image_view); + CustomGlideRequest.Builder + .from(requireContext(), songs.get(0).getCoverArtId()) + .build() + .into(coverAlbum); + + TextView groupNameView = view.findViewById(R.id.group_name_text_view); + groupNameView.setText(MusicUtil.getReadableString(this.groupName)); + groupNameView.setSelected(true); + + TextView playRandom = view.findViewById(R.id.play_random_text_view); + playRandom.setOnClickListener(v -> { + Collections.shuffle(songs); + + MediaManager.startQueue(mediaBrowserListenableFuture, songs, 0); + ((MainActivity) requireActivity()).setBottomSheetInPeek(true); + + dismissBottomSheet(); + }); + + TextView playNext = view.findViewById(R.id.play_next_text_view); + playNext.setOnClickListener(v -> { + MediaManager.enqueue(mediaBrowserListenableFuture, songs, true); + ((MainActivity) requireActivity()).setBottomSheetInPeek(true); + + dismissBottomSheet(); + } + ); + + TextView addToQueue = view.findViewById(R.id.add_to_queue_text_view); + addToQueue.setOnClickListener(v -> { + MediaManager.enqueue(mediaBrowserListenableFuture, songs, false); + ((MainActivity) requireActivity()).setBottomSheetInPeek(true); + + dismissBottomSheet(); + }); + + TextView removeAll = view.findViewById(R.id.remove_all_text_view); + + removeAll.setOnClickListener(v -> { + List mediaItems = MappingUtil.mapDownloads(songs); + List downloads = songs.stream().map(Download::new).collect(Collectors.toList()); + DownloadUtil.getDownloadTracker(requireContext()).remove(mediaItems, downloads); + dismissBottomSheet(); + }); + } + + @Override + public void onClick(View v) { + dismissBottomSheet(); + } + + private void dismissBottomSheet() { + dismiss(); + } + + private void initializeMediaBrowser() { + mediaBrowserListenableFuture = new MediaBrowser.Builder(requireContext(), new SessionToken(requireContext(), new ComponentName(requireContext(), MediaService.class))).buildAsync(); + } + + private void releaseMediaBrowser() { + MediaBrowser.releaseFuture(mediaBrowserListenableFuture); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/tempo/util/Constants.kt b/app/src/main/java/com/cappielloantonio/tempo/util/Constants.kt index 8a007cdf..7d35740f 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/util/Constants.kt +++ b/app/src/main/java/com/cappielloantonio/tempo/util/Constants.kt @@ -79,6 +79,8 @@ object Constants { const val DOWNLOAD_TYPE_TRACK = "download_type_track" const val DOWNLOAD_TYPE_ALBUM = "download_type_album" const val DOWNLOAD_TYPE_ARTIST = "download_type_artist" + const val DOWNLOAD_TYPE_GROUP = "download_type_group" + const val DOWNLOAD_TYPE_GROUP_NAME = "download_type_group_name" const val DOWNLOAD_TYPE_GENRE = "download_type_genre" const val DOWNLOAD_TYPE_YEAR = "download_type_year" diff --git a/app/src/main/res/layout/bottom_sheet_downloaded_dialog.xml b/app/src/main/res/layout/bottom_sheet_downloaded_dialog.xml new file mode 100644 index 00000000..d36831bf --- /dev/null +++ b/app/src/main/res/layout/bottom_sheet_downloaded_dialog.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 4623d084..d637b345 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -315,6 +315,11 @@ android:name="com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog.AlbumBottomSheetDialog" android:label="AlbumBottomSheetDialog" tools:layout="@layout/bottom_sheet_album_dialog" /> + Künstler Genre Jahr + Mischen + Nächsten Titel spielen + Zur Warteschlange hinzufügen + Alle entfernen \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9f7f6a92..084ef31b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -300,6 +300,10 @@ Artist Genre Year + Shuffle + Play next + Add to queue + Remove all OK Track info Title