From e2ddbdf6c94b89e59f4dcf11b012f2180bf2521e Mon Sep 17 00:00:00 2001 From: CappielloAntonio Date: Fri, 13 Aug 2021 17:29:37 +0200 Subject: [PATCH] Implemented rating system for song, album and artist (album and artist do not retrieve rating from server) --- .idea/misc.xml | 1 + .../com/cappielloantonio/play/model/Song.java | 24 +++-- .../play/repository/SongRepository.java | 23 +++++ .../subsonic/models/SubsonicResponse.java | 1 + .../fragment/PlayerBottomSheetFragment.java | 11 +++ .../AlbumBottomSheetDialog.java | 12 +++ .../ArtistBottomSheetDialog.java | 12 +++ .../SongBottomSheetDialog.java | 12 +++ .../play/ui/fragment/dialog/RatingDialog.java | 82 ++++++++++++++++ .../play/util/MappingUtil.java | 4 + .../viewmodel/PlayerBottomSheetViewModel.java | 5 + .../play/viewmodel/RatingViewModel.java | 96 +++++++++++++++++++ app/src/main/res/layout/dialog_rating.xml | 22 +++++ app/src/main/res/values-night/colors.xml | 3 + app/src/main/res/values/colors.xml | 2 + 15 files changed, 303 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/com/cappielloantonio/play/ui/fragment/dialog/RatingDialog.java create mode 100644 app/src/main/java/com/cappielloantonio/play/viewmodel/RatingViewModel.java create mode 100644 app/src/main/res/layout/dialog_rating.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 708be2f4..e826b7cf 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -30,6 +30,7 @@ + diff --git a/app/src/main/java/com/cappielloantonio/play/model/Song.java b/app/src/main/java/com/cappielloantonio/play/model/Song.java index d4fdff19..8ee95003 100644 --- a/app/src/main/java/com/cappielloantonio/play/model/Song.java +++ b/app/src/main/java/com/cappielloantonio/play/model/Song.java @@ -42,6 +42,7 @@ public class Song implements Parcelable { private long added; private int playCount; private long lastPlay; + private int rating; public Song() { this.id = UUID.randomUUID().toString(); @@ -67,6 +68,7 @@ public class Song implements Parcelable { this.added = child.getCreated().getTime(); this.playCount = 0; this.lastPlay = 0; + this.rating = child.getUserRating() != null ? child.getUserRating() : 0; } public Song(Queue queue) { @@ -251,14 +253,22 @@ public class Song implements Parcelable { this.playCount = playCount; } + public int getRating() { + return rating; + } + + public void setRating(int rating) { + this.rating = rating; + } + /* - Log.i(TAG, "increasePlayCount: " + isIncreased); - * Incremento il numero di ascolti solo se ho ascoltato la canzone da più tempo di: - * tempo dell'ultimo ascolto - (durata_canzone / 2) - * Ritorno un booleano - * Se vero, allora SongRepository scriverà nd DB l'incremento dell'ascolto - * Se falso, SongRepository non scriverà nulla nel db - */ + Log.i(TAG, "increasePlayCount: " + isIncreased); + * Incremento il numero di ascolti solo se ho ascoltato la canzone da più tempo di: + * tempo dell'ultimo ascolto - (durata_canzone / 2) + * Ritorno un booleano + * Se vero, allora SongRepository scriverà nd DB l'incremento dell'ascolto + * Se falso, SongRepository non scriverà nulla nel db + */ public boolean nowPlaying() { long startPlayTime = Instant.now().toEpochMilli(); diff --git a/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java b/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java index 0bd913fd..f6d2a6a4 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java @@ -230,4 +230,27 @@ public class SongRepository { return songsByGenre; } + + public MutableLiveData getSong(String id) { + MutableLiveData song = new MutableLiveData<>(); + + App.getSubsonicClientInstance(application, false) + .getBrowsingClient() + .getSong(id) + .enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.body().getStatus().getValue().equals(ResponseStatus.OK)) { + song.setValue(MappingUtil.mapSong(response.body().getSong())); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + + } + }); + + return song; + } } diff --git a/app/src/main/java/com/cappielloantonio/play/subsonic/models/SubsonicResponse.java b/app/src/main/java/com/cappielloantonio/play/subsonic/models/SubsonicResponse.java index a496a188..97754522 100644 --- a/app/src/main/java/com/cappielloantonio/play/subsonic/models/SubsonicResponse.java +++ b/app/src/main/java/com/cappielloantonio/play/subsonic/models/SubsonicResponse.java @@ -56,6 +56,7 @@ public class SubsonicResponse { private NowPlaying nowPlaying; private VideoInfo videoInfo; private Videos videos; + @Element(name = "song") private Child song; @Element(name = "album") private AlbumWithSongsID3 album; diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java index 09680c86..8265e6d6 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java @@ -29,6 +29,7 @@ import com.cappielloantonio.play.interfaces.MusicServiceEventListener; import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.service.MusicPlayerRemote; import com.cappielloantonio.play.ui.activity.MainActivity; +import com.cappielloantonio.play.ui.fragment.dialog.RatingDialog; import com.cappielloantonio.play.util.MappingUtil; import com.cappielloantonio.play.util.MusicUtil; import com.cappielloantonio.play.util.PreferenceUtil; @@ -212,6 +213,16 @@ public class PlayerBottomSheetFragment extends Fragment implements MusicServiceE private void initFavoriteButtonClick() { bind.playerBodyLayout.buttonFavorite.setOnClickListener(v -> playerBottomSheetViewModel.setFavorite()); + bind.playerBodyLayout.buttonFavorite.setOnLongClickListener(v -> { + Bundle bundle = new Bundle(); + bundle.putParcelable("song_object", playerBottomSheetViewModel.getCurrentSong()); + + RatingDialog dialog = new RatingDialog(); + dialog.setArguments(bundle); + dialog.show(requireActivity().getSupportFragmentManager(), null); + + return true; + }); } private void initMusicCommandButton() { diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java index c3630015..86d17cd1 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java @@ -26,6 +26,7 @@ import com.cappielloantonio.play.repository.AlbumRepository; import com.cappielloantonio.play.repository.QueueRepository; import com.cappielloantonio.play.service.MusicPlayerRemote; import com.cappielloantonio.play.ui.activity.MainActivity; +import com.cappielloantonio.play.ui.fragment.dialog.RatingDialog; import com.cappielloantonio.play.util.DownloadUtil; import com.cappielloantonio.play.util.MusicUtil; import com.cappielloantonio.play.viewmodel.AlbumBottomSheetViewModel; @@ -93,6 +94,17 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements albumBottomSheetViewModel.setFavorite(); dismissBottomSheet(); }); + favoriteToggle.setOnLongClickListener(v -> { + Bundle bundle = new Bundle(); + bundle.putParcelable("album_object", album); + + RatingDialog dialog = new RatingDialog(); + dialog.setArguments(bundle); + dialog.show(requireActivity().getSupportFragmentManager(), null); + + dismissBottomSheet(); + return true; + }); playRadio = view.findViewById(R.id.play_radio_text_view); playRadio.setOnClickListener(v -> { diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/ArtistBottomSheetDialog.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/ArtistBottomSheetDialog.java index b118d1dd..685e55dc 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/ArtistBottomSheetDialog.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/ArtistBottomSheetDialog.java @@ -25,6 +25,7 @@ import com.cappielloantonio.play.repository.ArtistRepository; import com.cappielloantonio.play.repository.QueueRepository; import com.cappielloantonio.play.service.MusicPlayerRemote; import com.cappielloantonio.play.ui.activity.MainActivity; +import com.cappielloantonio.play.ui.fragment.dialog.RatingDialog; import com.cappielloantonio.play.util.MusicUtil; import com.cappielloantonio.play.viewmodel.ArtistBottomSheetViewModel; import com.google.android.material.bottomsheet.BottomSheetDialogFragment; @@ -82,6 +83,17 @@ public class ArtistBottomSheetDialog extends BottomSheetDialogFragment implement artistBottomSheetViewModel.setFavorite(); dismissBottomSheet(); }); + favoriteToggle.setOnLongClickListener(v -> { + Bundle bundle = new Bundle(); + bundle.putParcelable("artist_object", artist); + + RatingDialog dialog = new RatingDialog(); + dialog.setArguments(bundle); + dialog.show(requireActivity().getSupportFragmentManager(), null); + + dismissBottomSheet(); + return true; + }); playRadio = view.findViewById(R.id.play_radio_text_view); playRadio.setOnClickListener(v -> { diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java index 9248b681..cdd87170 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java @@ -26,6 +26,7 @@ import com.cappielloantonio.play.repository.SongRepository; import com.cappielloantonio.play.service.MusicPlayerRemote; import com.cappielloantonio.play.ui.activity.MainActivity; import com.cappielloantonio.play.ui.fragment.dialog.PlaylistChooserDialog; +import com.cappielloantonio.play.ui.fragment.dialog.RatingDialog; import com.cappielloantonio.play.ui.fragment.dialog.ServerSignupDialog; import com.cappielloantonio.play.util.DownloadUtil; import com.cappielloantonio.play.util.MusicUtil; @@ -93,6 +94,17 @@ public class SongBottomSheetDialog extends BottomSheetDialogFragment implements songBottomSheetViewModel.setFavorite(); dismissBottomSheet(); }); + favoriteToggle.setOnLongClickListener(v -> { + Bundle bundle = new Bundle(); + bundle.putParcelable("song_object", song); + + RatingDialog dialog = new RatingDialog(); + dialog.setArguments(bundle); + dialog.show(requireActivity().getSupportFragmentManager(), null); + + dismissBottomSheet(); + return true; + }); playRadio = view.findViewById(R.id.play_radio_text_view); playRadio.setOnClickListener(v -> { diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/dialog/RatingDialog.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/dialog/RatingDialog.java new file mode 100644 index 00000000..3342e9f4 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/dialog/RatingDialog.java @@ -0,0 +1,82 @@ +package com.cappielloantonio.play.ui.fragment.dialog; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; + +import androidx.fragment.app.DialogFragment; +import androidx.lifecycle.ViewModelProvider; + +import com.cappielloantonio.play.R; +import com.cappielloantonio.play.databinding.DialogRatingBinding; +import com.cappielloantonio.play.ui.activity.MainActivity; +import com.cappielloantonio.play.viewmodel.RatingViewModel; + +import java.util.Objects; + +public class RatingDialog extends DialogFragment { + private static final String TAG = "ServerSignupDialog"; + + private DialogRatingBinding bind; + private MainActivity activity; + private Context context; + private RatingViewModel ratingViewModel; + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + activity = (MainActivity) getActivity(); + context = requireContext(); + + bind = DialogRatingBinding.inflate(LayoutInflater.from(requireContext())); + ratingViewModel = new ViewModelProvider(requireActivity()).get(RatingViewModel.class); + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AppTheme_AlertDialog); + + builder.setView(bind.getRoot()) + .setTitle("Rate") + .setNegativeButton("Cancel", (dialog, id) -> dialog.cancel()) + .setPositiveButton("Save", (dialog, id) -> { + ratingViewModel.rate((int) bind.ratingBar.getRating()); + }); + + return builder.create(); + } + + @Override + public void onStart() { + super.onStart(); + + setElementInfo(); + setButtonColor(); + setRating(); + } + + private void setElementInfo() { + if (getArguments() != null) { + if (getArguments().getParcelable("song_object") != null) { + ratingViewModel.setSong(getArguments().getParcelable("song_object")); + } else if (getArguments().getParcelable("album_object") != null) { + ratingViewModel.setAlbum(getArguments().getParcelable("album_object")); + } else if (getArguments().getParcelable("artist_object") != null) { + ratingViewModel.setArtist(getArguments().getParcelable("artist_object")); + } + } + } + + private void setButtonColor() { + ((AlertDialog) Objects.requireNonNull(getDialog())).getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(getResources().getColor(R.color.colorAccent, null)); + ((AlertDialog) Objects.requireNonNull(getDialog())).getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(getResources().getColor(R.color.colorAccent, null)); + } + + private void setRating() { + if (ratingViewModel.getSong() != null) { + ratingViewModel.getLiveSong().observe(requireActivity(), song -> bind.ratingBar.setRating(song.getRating())); + } else if (ratingViewModel.getAlbum() != null) { + ratingViewModel.getLiveAlbum().observe(requireActivity(), album -> bind.ratingBar.setRating(/*album.getRating()*/ 0)); + } else if (ratingViewModel.getArtist() != null) { + ratingViewModel.getLiveArtist().observe(requireActivity(), artist -> bind.ratingBar.setRating(/*artist.getRating()*/ 0)); + } + } +} diff --git a/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java b/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java index a22f594a..c3858330 100644 --- a/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java +++ b/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java @@ -30,6 +30,10 @@ public class MappingUtil { return songs; } + public static Song mapSong(Child child) { + return new Song(child); + } + public static ArrayList mapAlbum(List albumID3List) { ArrayList albums = new ArrayList(); diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java index cfb884d1..ad48295c 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java @@ -35,6 +35,11 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel { return queueSong; } + public Song getCurrentSong() { + return MusicPlayerRemote.getCurrentSong(); + } + + public void setFavorite() { Song song = MusicPlayerRemote.getCurrentSong(); diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/RatingViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/RatingViewModel.java new file mode 100644 index 00000000..5920e63d --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/RatingViewModel.java @@ -0,0 +1,96 @@ +package com.cappielloantonio.play.viewmodel; + +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; + +import com.cappielloantonio.play.model.Album; +import com.cappielloantonio.play.model.Artist; +import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.repository.AlbumRepository; +import com.cappielloantonio.play.repository.ArtistRepository; +import com.cappielloantonio.play.repository.SongRepository; + +public class RatingViewModel extends AndroidViewModel { + private SongRepository songRepository; + private AlbumRepository albumRepository; + private ArtistRepository artistRepository; + + private Song song; + private Album album; + private Artist artist; + + public RatingViewModel(@NonNull Application application) { + super(application); + + songRepository = new SongRepository(application); + albumRepository = new AlbumRepository(application); + artistRepository = new ArtistRepository(application); + } + + public Song getSong() { + return song; + } + + public LiveData getLiveSong() { + return songRepository.getSong(song.getId()); + } + + public void setSong(Song song) { + this.song = song; + this.album = null; + this.artist = null; + } + + public Album getAlbum() { + return album; + } + + public LiveData getLiveAlbum() { + return albumRepository.getAlbum(album.getId()); + } + + public void setAlbum(Album album) { + this.song = null; + this.album = album; + this.artist = null; + } + + public Artist getArtist() { + return artist; + } + + public LiveData getLiveArtist() { + return artistRepository.getArtist(artist.getId()); + } + + public void setArtist(Artist artist) { + this.song = null; + this.album = null; + this.artist = artist; + } + + public int getItemRating() { + if (song != null) { + return song.getRating(); + } else if (album != null) { + return 0; + } else if (artist != null) { + return 0; + } else { + return 0; + } + } + + public void rate(int star) { + if (song != null) { + songRepository.setRating(song.getId(), star); + } else if (album != null) { + albumRepository.setRating(album.getId(), star); + } else if (artist != null) { + artistRepository.setRating(artist.getId(), star); + } + } +} diff --git a/app/src/main/res/layout/dialog_rating.xml b/app/src/main/res/layout/dialog_rating.xml new file mode 100644 index 00000000..af29b0e7 --- /dev/null +++ b/app/src/main/res/layout/dialog_rating.xml @@ -0,0 +1,22 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 72f509d2..580cbce2 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -31,5 +31,8 @@ #707070 #606060 #1D1D1D + + #733ae6 + #1D1D1D diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 8d32cc43..9a06de73 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -37,4 +37,6 @@ #FFFFFF + #3700B3 + #f0f0f0 \ No newline at end of file