mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 17:43:32 +00:00
Implemented rating system for song, album and artist (album and artist do not retrieve rating from server)
This commit is contained in:
parent
055ac44cf6
commit
e2ddbdf6c9
15 changed files with 303 additions and 7 deletions
1
.idea/misc.xml
generated
1
.idea/misc.xml
generated
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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 -> {
|
||||
|
|
|
|||
|
|
@ -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 -> {
|
||||
|
|
|
|||
|
|
@ -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 -> {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
|
|||
return queueSong;
|
||||
}
|
||||
|
||||
public Song getCurrentSong() {
|
||||
return MusicPlayerRemote.getCurrentSong();
|
||||
}
|
||||
|
||||
|
||||
public void setFavorite() {
|
||||
Song song = MusicPlayerRemote.getCurrentSong();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
app/src/main/res/layout/dialog_rating.xml
Normal file
22
app/src/main/res/layout/dialog_rating.xml
Normal 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>
|
||||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -37,4 +37,6 @@
|
|||
|
||||
<color name="white">#FFFFFF</color>
|
||||
|
||||
<color name="startTintColor">#3700B3</color>
|
||||
<color name="startBackgroundTintColor">#f0f0f0</color>
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue