Implemented rating system for song, album and artist (album and artist do not retrieve rating from server)

This commit is contained in:
CappielloAntonio 2021-08-13 17:29:37 +02:00
parent 055ac44cf6
commit e2ddbdf6c9
15 changed files with 303 additions and 7 deletions

1
.idea/misc.xml generated
View file

@ -30,6 +30,7 @@
<entry key="app/src/main/res/layout/fragment_artist_page.xml" value="0.1" />
<entry key="app/src/main/res/layout/fragment_home.xml" value="0.2212962962962963" />
<entry key="app/src/main/res/layout/fragment_login.xml" value="0.3166496424923391" />
<entry key="app/src/main/res/layout/fragment_player_bottom_sheet.xml" value="0.3166496424923391" />
<entry key="app/src/main/res/layout/fragment_playlist_catalogue.xml" value="0.3229166666666667" />
<entry key="app/src/main/res/layout/fragment_playlist_page.xml" value="0.3229166666666667" />
<entry key="app/src/main/res/layout/item_home_discover_song.xml" value="0.3166496424923391" />

View file

@ -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();

View file

@ -230,4 +230,27 @@ public class SongRepository {
return songsByGenre;
}
public MutableLiveData<Song> getSong(String id) {
MutableLiveData<Song> song = new MutableLiveData<>();
App.getSubsonicClientInstance(application, false)
.getBrowsingClient()
.getSong(id)
.enqueue(new Callback<SubsonicResponse>() {
@Override
public void onResponse(Call<SubsonicResponse> call, Response<SubsonicResponse> response) {
if (response.body().getStatus().getValue().equals(ResponseStatus.OK)) {
song.setValue(MappingUtil.mapSong(response.body().getSong()));
}
}
@Override
public void onFailure(Call<SubsonicResponse> call, Throwable t) {
}
});
return song;
}
}

View file

@ -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;

View file

@ -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() {

View file

@ -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 -> {

View file

@ -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 -> {

View file

@ -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 -> {

View file

@ -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));
}
}
}

View file

@ -30,6 +30,10 @@ public class MappingUtil {
return songs;
}
public static Song mapSong(Child child) {
return new Song(child);
}
public static ArrayList<Album> mapAlbum(List<AlbumID3> albumID3List) {
ArrayList<Album> albums = new ArrayList();

View file

@ -35,6 +35,11 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
return queueSong;
}
public Song getCurrentSong() {
return MusicPlayerRemote.getCurrentSong();
}
public void setFavorite() {
Song song = MusicPlayerRemote.getCurrentSong();

View file

@ -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<Song> 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<Album> 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<Artist> 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);
}
}
}

View file

@ -0,0 +1,22 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RatingBar
android:id="@+id/rating_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="12dp"
android:stepSize="1"
android:numStars="5"
android:rating="0"
android:progressTint="@color/startTintColor"
android:progressBackgroundTint="@color/startBackgroundTintColor"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -31,5 +31,8 @@
<color name="chipBorderColor">#707070</color>
<color name="chipSelectedBackgroundColor">#606060</color>
<color name="chipUnelectedBackgroundColor">#1D1D1D</color>
<color name="startTintColor">#733ae6</color>
<color name="startBackgroundTintColor">#1D1D1D</color>
</resources>

View file

@ -37,4 +37,6 @@
<color name="white">#FFFFFF</color>
<color name="startTintColor">#3700B3</color>
<color name="startBackgroundTintColor">#f0f0f0</color>
</resources>