diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/SimilarTrackAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/SimilarTrackAdapter.java new file mode 100644 index 00000000..54385a54 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/adapter/SimilarTrackAdapter.java @@ -0,0 +1,120 @@ +package com.cappielloantonio.play.adapter; + +import android.content.Context; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.navigation.Navigation; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.cappielloantonio.play.App; +import com.cappielloantonio.play.R; +import com.cappielloantonio.play.glide.CustomGlideRequest; +import com.cappielloantonio.play.interfaces.MediaCallback; +import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.repository.QueueRepository; +import com.cappielloantonio.play.repository.SongRepository; +import com.cappielloantonio.play.service.MusicPlayerRemote; +import com.cappielloantonio.play.ui.activity.MainActivity; +import com.cappielloantonio.play.util.MusicUtil; + +import java.util.ArrayList; +import java.util.List; + + +public class SimilarTrackAdapter extends RecyclerView.Adapter { + private static final String TAG = "SimilarTrackAdapter"; + + private final MainActivity mainActivity; + private final Context context; + private final LayoutInflater mInflater; + + private List songs; + + public SimilarTrackAdapter(MainActivity mainActivity, Context context) { + this.mainActivity = mainActivity; + this.context = context; + this.mInflater = LayoutInflater.from(context); + this.songs = new ArrayList<>(); + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = mInflater.inflate(R.layout.item_home_track, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + Song song = songs.get(position); + + holder.textTitle.setText(MusicUtil.getReadableString(song.getTitle())); + holder.textAlbum.setText(MusicUtil.getReadableString(song.getAlbumName())); + + CustomGlideRequest.Builder + .from(context, song.getPrimary(), CustomGlideRequest.SONG_PIC, null) + .build() + .transform(new RoundedCorners(CustomGlideRequest.CORNER_RADIUS)) + .into(holder.cover); + } + + @Override + public int getItemCount() { + return songs.size(); + } + + public void setItems(List songs) { + this.songs = songs; + notifyDataSetChanged(); + } + + public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView textTitle; + TextView textAlbum; + ImageView cover; + + ViewHolder(View itemView) { + super(itemView); + + textTitle = itemView.findViewById(R.id.title_track_label); + textAlbum = itemView.findViewById(R.id.album_track_label); + cover = itemView.findViewById(R.id.track_cover_image_view); + + itemView.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + List opener = new ArrayList<>(); + opener.add(songs.get(getBindingAdapterPosition())); + MusicPlayerRemote.openQueue(opener, 0, true); + + QueueRepository queueRepository = new QueueRepository(App.getInstance()); + queueRepository.insertAllAndStartNew(opener); + + mainActivity.isBottomSheetInPeek(true); + mainActivity.setBottomSheetMusicInfo(songs.get(getBindingAdapterPosition())); + + SongRepository songRepository = new SongRepository(App.getInstance()); + songRepository.getInstantMix(songs.get(getBindingAdapterPosition()), 20, new MediaCallback() { + @Override + public void onError(Exception exception) { + Log.e(TAG, "onError: " + exception.getMessage()); + } + + @Override + public void onLoadMedia(List media) { + MusicPlayerRemote.enqueue((List) media); + } + }); + } + } +} diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/RecentMusicAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/TrackAdapter.java similarity index 93% rename from app/src/main/java/com/cappielloantonio/play/adapter/RecentMusicAdapter.java rename to app/src/main/java/com/cappielloantonio/play/adapter/TrackAdapter.java index 407b78ec..b8b3e3f8 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/RecentMusicAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/TrackAdapter.java @@ -2,7 +2,6 @@ package com.cappielloantonio.play.adapter; import android.content.Context; import android.os.Bundle; -import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -10,7 +9,6 @@ import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.fragment.app.FragmentManager; import androidx.navigation.Navigation; import androidx.recyclerview.widget.RecyclerView; @@ -30,7 +28,7 @@ import java.util.List; /** * Adapter per i brani recenti in home */ -public class RecentMusicAdapter extends RecyclerView.Adapter { +public class TrackAdapter extends RecyclerView.Adapter { private static final String TAG = "RecentMusicAdapter"; private final MainActivity mainActivity; @@ -39,7 +37,7 @@ public class RecentMusicAdapter extends RecyclerView.Adapter songs; - public RecentMusicAdapter(MainActivity mainActivity, Context context) { + public TrackAdapter(MainActivity mainActivity, Context context) { this.mainActivity = mainActivity; this.context = context; this.mInflater = LayoutInflater.from(context); 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 f6d2a6a4..b698e6be 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java @@ -29,7 +29,7 @@ public class SongRepository { this.application = application; } - public MutableLiveData> getStarredSongs() { + public MutableLiveData> getStarredSongs(boolean random, int size) { MutableLiveData> starredSongs = new MutableLiveData<>(); App.getSubsonicClientInstance(application, false) @@ -40,7 +40,13 @@ public class SongRepository { public void onResponse(Call call, Response response) { if (response.body().getStatus().getValue().equals(ResponseStatus.OK)) { List songs = new ArrayList<>(MappingUtil.mapSong(response.body().getStarred2().getSongs())); - starredSongs.setValue(songs); + + if (!random) { + starredSongs.setValue(songs); + } else { + Collections.shuffle(songs); + starredSongs.setValue(songs.subList(0, Math.min(size, songs.size()))); + } } } diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java index e0b3f76f..21d304ba 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java @@ -21,7 +21,8 @@ import com.cappielloantonio.play.adapter.AlbumAdapter; import com.cappielloantonio.play.adapter.AlbumHorizontalAdapter; import com.cappielloantonio.play.adapter.ArtistHorizontalAdapter; import com.cappielloantonio.play.adapter.DiscoverSongAdapter; -import com.cappielloantonio.play.adapter.RecentMusicAdapter; +import com.cappielloantonio.play.adapter.SimilarTrackAdapter; +import com.cappielloantonio.play.adapter.TrackAdapter; import com.cappielloantonio.play.adapter.SongHorizontalAdapter; import com.cappielloantonio.play.adapter.YearAdapter; import com.cappielloantonio.play.databinding.FragmentHomeBinding; @@ -49,7 +50,8 @@ public class HomeFragment extends Fragment { private SongHorizontalAdapter starredSongAdapter; private AlbumHorizontalAdapter starredAlbumAdapter; private ArtistHorizontalAdapter starredArtistAdapter; - private RecentMusicAdapter dowanloadedMusicAdapter; + private TrackAdapter dowanloadedMusicAdapter; + private SimilarTrackAdapter similarMusicAdapter; @Nullable @Override @@ -70,6 +72,7 @@ public class HomeFragment extends Fragment { super.onViewCreated(view, savedInstanceState); initDiscoverSongSlideView(); + initSimilarSongView(); initMostPlayedAlbumView(); initRecentPlayedAlbumView(); initStarredTracksView(); @@ -143,6 +146,11 @@ public class HomeFragment extends Fragment { return true; }); + bind.similarTracksTextViewRefreshable.setOnLongClickListener(v -> { + homeViewModel.refreshSimilarSongSample(requireActivity()); + return true; + }); + bind.recentlyPlayedAlbumsTextViewRefreshable.setOnLongClickListener(v -> { homeViewModel.refreshRecentlyPlayedAlbumList(requireActivity()); return true; @@ -195,6 +203,28 @@ public class HomeFragment extends Fragment { setDiscoverSongSlideViewOffset(20, 16); } + private void initSimilarSongView() { + bind.similarTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)); + bind.similarTracksRecyclerView.setHasFixedSize(true); + + similarMusicAdapter = new SimilarTrackAdapter(activity, requireContext()); + bind.similarTracksRecyclerView.setAdapter(similarMusicAdapter); + homeViewModel.getStarredTracksSample().observe(requireActivity(), songs -> { + if (songs == null) { + if (bind != null) bind.homeSimilarTracksPlaceholder.placeholder.setVisibility(View.VISIBLE); + if (bind != null) bind.homeSimilarTracksSector.setVisibility(View.GONE); + } else { + if (bind != null) bind.homeSimilarTracksPlaceholder.placeholder.setVisibility(View.GONE); + if (bind != null) bind.homeSimilarTracksSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : View.GONE); + + similarMusicAdapter.setItems(songs); + } + }); + + CustomLinearSnapHelper similarSongSnapHelper = new CustomLinearSnapHelper(); + similarSongSnapHelper.attachToRecyclerView(bind.similarTracksRecyclerView); + } + private void initMostPlayedAlbumView() { bind.mostPlayedAlbumsRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)); bind.mostPlayedAlbumsRecyclerView.setHasFixedSize(true); @@ -360,7 +390,7 @@ public class HomeFragment extends Fragment { bind.downloadedTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)); bind.downloadedTracksRecyclerView.setHasFixedSize(true); - dowanloadedMusicAdapter = new RecentMusicAdapter(activity, requireContext()); + dowanloadedMusicAdapter = new TrackAdapter(activity, requireContext()); bind.downloadedTracksRecyclerView.setAdapter(dowanloadedMusicAdapter); homeViewModel.getDownloaded(requireActivity()).observe(requireActivity(), downloads -> { if (downloads == null) { @@ -404,6 +434,7 @@ public class HomeFragment extends Fragment { if (bind != null) { bind.homeLinearLayoutContainer.removeAllViews(); bind.homeLinearLayoutContainer.addView(bind.homeDiscoverSector); + bind.homeLinearLayoutContainer.addView(bind.homeSimilarTracksSector); bind.homeLinearLayoutContainer.addView(bind.homeRecentlyAddedAlbumsSector); bind.homeLinearLayoutContainer.addView(bind.homeFlashbackSector); bind.homeLinearLayoutContainer.addView(bind.homeStarredTracksSector); diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java index ef8e8eba..85ffbc7f 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java @@ -28,6 +28,8 @@ public class HomeViewModel extends AndroidViewModel { private final DownloadRepository downloadRepository; private final MutableLiveData> dicoverSongSample = new MutableLiveData<>(null); + private final MutableLiveData> starredTracksSample = new MutableLiveData<>(null); + private final MutableLiveData> mostPlayedAlbumSample = new MutableLiveData<>(null); private final MutableLiveData> recentlyPlayedAlbumSample = new MutableLiveData<>(null); private final MutableLiveData> years = new MutableLiveData<>(null); @@ -46,19 +48,24 @@ public class HomeViewModel extends AndroidViewModel { downloadRepository = new DownloadRepository(application); songRepository.getRandomSample(10, null, null).observeForever(dicoverSongSample::postValue); + songRepository.getStarredSongs(true, 10).observeForever(starredTracksSample::postValue); } public LiveData> getDiscoverSongSample() { return dicoverSongSample; } + public LiveData> getStarredTracksSample() { + return starredTracksSample; + } + public LiveData> getYearList(LifecycleOwner owner) { albumRepository.getDecades().observe(owner, years::postValue); return years; } public LiveData> getStarredTracks(LifecycleOwner owner) { - songRepository.getStarredSongs().observe(owner, starredTracks::postValue); + songRepository.getStarredSongs(false, -1).observe(owner, starredTracks::postValue); return starredTracks; } @@ -96,8 +103,12 @@ public class HomeViewModel extends AndroidViewModel { songRepository.getRandomSample(10, null, null).observe(owner, dicoverSongSample::postValue); } + public void refreshSimilarSongSample(LifecycleOwner owner) { + songRepository.getStarredSongs(true, 10).observe(owner, starredTracksSample::postValue); + } + public void refreshStarredTracks(LifecycleOwner owner) { - songRepository.getStarredSongs().observe(owner, starredTracks::postValue); + songRepository.getStarredSongs(false, -1).observe(owner, starredTracks::postValue); } public void refreshStarredAlbums(LifecycleOwner owner) { diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/SongListPageViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/SongListPageViewModel.java index 2516cb9d..7bb5f2f3 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/SongListPageViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/SongListPageViewModel.java @@ -67,7 +67,7 @@ public class SongListPageViewModel extends AndroidViewModel { songList = songRepository.getRandomSample(500, year, year + 10); break; case Song.STARRED: - songList = songRepository.getStarredSongs(); + songList = songRepository.getStarredSongs(false, -1); break; case Song.DOWNLOADED: songList.setValue(MappingUtil.mapDownload(downloadRepository.getLiveDownload())); diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index d3d52a23..43d34111 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -71,6 +71,41 @@ layout="@layout/item_placehoder_discovery" android:visibility="gone"/> + + + + + + + + + + - - + +