Separated Suggestions from Home sections

This commit is contained in:
Prathamesh More 2022-01-07 23:56:14 +05:30
parent 75cdf4d57f
commit 80f3926210
9 changed files with 114 additions and 122 deletions

View file

@ -15,12 +15,10 @@
package code.name.monkey.retromusic.adapter package code.name.monkey.retromusic.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.os.SystemClock
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
@ -30,30 +28,22 @@ import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.adapter.album.AlbumAdapter import code.name.monkey.retromusic.adapter.album.AlbumAdapter
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.fragments.home.HomeFragment import code.name.monkey.retromusic.fragments.home.HomeFragment
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.IAlbumClickListener import code.name.monkey.retromusic.interfaces.IAlbumClickListener
import code.name.monkey.retromusic.interfaces.IArtistClickListener import code.name.monkey.retromusic.interfaces.IArtistClickListener
import code.name.monkey.retromusic.interfaces.IGenreClickListener import code.name.monkey.retromusic.interfaces.IGenreClickListener
import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.model.*
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import com.google.android.material.card.MaterialCardView
class HomeAdapter( class HomeAdapter(
private val activity: AppCompatActivity private val activity: AppCompatActivity
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), IArtistClickListener, IAlbumClickListener, ) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), IArtistClickListener, IAlbumClickListener,
IGenreClickListener { IGenreClickListener {
private var mLastClickTime: Long = 0
private var list = listOf<Home>() private var list = listOf<Home>()
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
@ -68,13 +58,7 @@ class HomeAdapter(
FAVOURITES -> PlaylistViewHolder(layout) FAVOURITES -> PlaylistViewHolder(layout)
TOP_ALBUMS, RECENT_ALBUMS -> AlbumViewHolder(layout) TOP_ALBUMS, RECENT_ALBUMS -> AlbumViewHolder(layout)
else -> { else -> {
SuggestionsViewHolder( ArtistViewHolder(layout)
LayoutInflater.from(activity).inflate(
R.layout.item_suggestions,
parent,
false
)
)
} }
} }
} }
@ -126,10 +110,6 @@ class HomeAdapter(
) )
} }
} }
SUGGESTIONS -> {
val viewHolder = holder as SuggestionsViewHolder
viewHolder.bindView(home)
}
FAVOURITES -> { FAVOURITES -> {
val viewHolder = holder as PlaylistViewHolder val viewHolder = holder as PlaylistViewHolder
viewHolder.bindView(home) viewHolder.bindView(home)
@ -174,52 +154,6 @@ class HomeAdapter(
} }
} }
private inner class SuggestionsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val images = listOf(
R.id.image1,
R.id.image2,
R.id.image3,
R.id.image4,
R.id.image5,
R.id.image6,
R.id.image7,
R.id.image8
)
fun bindView(home: Home) {
val color = ThemeStore.accentColor(activity)
itemView.findViewById<TextView>(R.id.message).apply {
setTextColor(color)
setOnClickListener {
if (SystemClock.elapsedRealtime() - mLastClickTime < 1000){
return@setOnClickListener
}
mLastClickTime = SystemClock.elapsedRealtime()
MusicPlayerRemote.playNext((home.arrayList as List<Song>).subList(0, 8))
if (!MusicPlayerRemote.isPlaying) {
MusicPlayerRemote.playNextSong()
}
}
}
itemView.findViewById<MaterialCardView>(R.id.card6).apply {
setCardBackgroundColor(ColorUtil.withAlpha(color, 0.12f))
}
images.forEachIndexed { index, id ->
itemView.findViewById<View>(id).setOnClickListener {
MusicPlayerRemote.playNext(home.arrayList[index] as Song)
if (!MusicPlayerRemote.isPlaying) {
MusicPlayerRemote.playNextSong()
}
}
GlideApp.with(activity)
.asBitmap()
.songCoverOptions(home.arrayList[index] as Song)
.load(RetroGlideExtension.getSongModel(home.arrayList[index] as Song))
.into(itemView.findViewById(id))
}
}
}
private inner class PlaylistViewHolder(view: View) : AbsHomeViewItem(view) { private inner class PlaylistViewHolder(view: View) : AbsHomeViewItem(view) {
fun bindView(home: Home) { fun bindView(home: Home) {
title.setText(home.titleRes) title.setText(home.titleRes)

View file

@ -40,6 +40,7 @@ class LibraryViewModel(
private val _paletteColor = MutableLiveData<Int>() private val _paletteColor = MutableLiveData<Int>()
private val home = MutableLiveData<List<Home>>() private val home = MutableLiveData<List<Home>>()
private val suggestions = MutableLiveData<List<Song>>()
private val albums = MutableLiveData<List<Album>>() private val albums = MutableLiveData<List<Album>>()
private val songs = MutableLiveData<List<Song>>() private val songs = MutableLiveData<List<Song>>()
private val artists = MutableLiveData<List<Artist>>() private val artists = MutableLiveData<List<Artist>>()
@ -56,6 +57,7 @@ class LibraryViewModel(
private fun loadLibraryContent() = viewModelScope.launch(IO) { private fun loadLibraryContent() = viewModelScope.launch(IO) {
fetchHomeSections() fetchHomeSections()
fetchSuggestions()
fetchSongs() fetchSongs()
fetchAlbums() fetchAlbums()
fetchArtists() fetchArtists()
@ -93,6 +95,10 @@ class LibraryViewModel(
return home return home
} }
fun getSuggestions(): LiveData<List<Song>> {
return suggestions
}
fun getFabMargin(): LiveData<Int> { fun getFabMargin(): LiveData<Int> {
return fabMargin return fabMargin
} }
@ -132,6 +138,10 @@ class LibraryViewModel(
home.postValue(repository.homeSections()) home.postValue(repository.homeSections())
} }
private suspend fun fetchSuggestions() {
suggestions.postValue(repository.suggestions())
}
fun search(query: String?, filter: Filter) { fun search(query: String?, filter: Filter) {
viewModelScope.launch(IO) { viewModelScope.launch(IO) {
val result = repository.search(query, filter) val result = repository.search(query, filter)
@ -147,6 +157,7 @@ class LibraryViewModel(
HomeSections -> fetchHomeSections() HomeSections -> fetchHomeSections()
Playlists -> fetchPlaylists() Playlists -> fetchPlaylists()
Genres -> fetchGenres() Genres -> fetchGenres()
Suggestions -> fetchSuggestions()
} }
} }
@ -391,4 +402,5 @@ enum class ReloadType {
HomeSections, HomeSections,
Playlists, Playlists,
Genres, Genres,
Suggestions
} }

View file

@ -28,4 +28,5 @@ class HomeBindingAdapter(
?: bannerHomeBinding?.homeContent?.recyclerView!! ?: bannerHomeBinding?.homeContent?.recyclerView!!
val titleWelcome = homeBinding?.titleWelcome ?: bannerHomeBinding?.titleWelcome!! val titleWelcome = homeBinding?.titleWelcome ?: bannerHomeBinding?.titleWelcome!!
val appNameText = homeBinding?.appNameText ?: bannerHomeBinding?.appNameText!! val appNameText = homeBinding?.appNameText ?: bannerHomeBinding?.appNameText!!
val suggestions = homeBinding?.homeContent?.suggestions ?: bannerHomeBinding?.homeContent?.suggestions!!
} }

View file

@ -28,7 +28,9 @@ import androidx.core.view.doOnPreDraw
import androidx.navigation.fragment.FragmentNavigatorExtras import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.common.ATHToolbarActivity import code.name.monkey.appthemehelper.common.ATHToolbarActivity
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.adapter.HomeAdapter import code.name.monkey.retromusic.adapter.HomeAdapter
@ -43,7 +45,9 @@ import code.name.monkey.retromusic.fragments.ReloadType
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.glide.GlideApp import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.IScrollHelper import code.name.monkey.retromusic.interfaces.IScrollHelper
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import com.google.android.gms.cast.framework.CastButtonFactory import com.google.android.gms.cast.framework.CastButtonFactory
import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.MaterialShapeDrawable
@ -76,6 +80,9 @@ class HomeFragment :
libraryViewModel.getHome().observe(viewLifecycleOwner, { libraryViewModel.getHome().observe(viewLifecycleOwner, {
homeAdapter.swapData(it) homeAdapter.swapData(it)
}) })
libraryViewModel.getSuggestions().observe(viewLifecycleOwner, {
loadSuggestions(it)
})
loadProfile() loadProfile()
setupTitle() setupTitle()
@ -151,6 +158,8 @@ class HomeFragment :
) )
) )
} }
// Reload suggestions
binding.suggestions.refreshButton.setOnClickListener { libraryViewModel.forceReload(ReloadType.Suggestions) }
} }
private fun getBinding(homeBanner: Boolean, view: View): HomeBindingAdapter { private fun getBinding(homeBanner: Boolean, view: View): HomeBindingAdapter {
@ -235,6 +244,47 @@ class HomeFragment :
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false) reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false)
} }
private fun loadSuggestions(songs: List<Song>) {
val images = listOf(
binding.suggestions.image1,
binding.suggestions.image2,
binding.suggestions.image3,
binding.suggestions.image4,
binding.suggestions.image5,
binding.suggestions.image6,
binding.suggestions.image7,
binding.suggestions.image8
)
val color = ThemeStore.accentColor(requireContext())
binding.suggestions.message.apply {
setTextColor(color)
setOnClickListener {
it.isClickable = false
it.postDelayed({ it.isClickable = true }, 500)
MusicPlayerRemote.playNext(songs.subList(0, 8))
if (!MusicPlayerRemote.isPlaying) {
MusicPlayerRemote.playNextSong()
}
}
}
binding.suggestions.card6.setCardBackgroundColor(ColorUtil.withAlpha(color, 0.12f))
images.forEachIndexed { index, imageView ->
imageView.setOnClickListener {
it.isClickable = false
it.postDelayed({ it.isClickable = true }, 500)
MusicPlayerRemote.playNext(songs)
if (!MusicPlayerRemote.isPlaying) {
MusicPlayerRemote.playNextSong()
}
}
GlideApp.with(this)
.asBitmap()
.songCoverOptions(songs[index])
.load(RetroGlideExtension.getSongModel(songs[index]))
.into(imageView)
}
}
companion object { companion object {
const val TAG: String = "BannerHomeFragment" const val TAG: String = "BannerHomeFragment"

View file

@ -69,6 +69,7 @@ interface Repository {
suspend fun recentAlbumsHome(): Home suspend fun recentAlbumsHome(): Home
suspend fun favoritePlaylistHome(): Home suspend fun favoritePlaylistHome(): Home
suspend fun suggestionsHome(): Home suspend fun suggestionsHome(): Home
suspend fun suggestions(): List<Song>
suspend fun genresHome(): Home suspend fun genresHome(): Home
suspend fun playlists(): Home suspend fun playlists(): Home
suspend fun homeSections(): List<Home> suspend fun homeSections(): List<Home>
@ -240,21 +241,17 @@ class RealRepository(
override suspend fun homeSections(): List<Home> { override suspend fun homeSections(): List<Home> {
val homeSections = mutableListOf<Home>() val homeSections = mutableListOf<Home>()
val sections: List<Home> = listOf( val sections: List<Home> = listOf(
suggestionsHome(),
topArtistsHome(), topArtistsHome(),
topAlbumsHome(), topAlbumsHome(),
recentArtistsHome(), recentArtistsHome(),
recentAlbumsHome(), recentAlbumsHome(),
favoritePlaylistHome() favoritePlaylistHome()
// genresHome()
) )
for (section in sections) { for (section in sections) {
if (section.arrayList.isNotEmpty()) { if (section.arrayList.isNotEmpty()) {
if (section.homeSection != SUGGESTIONS || PreferenceUtil.homeSuggestions) {
homeSections.add(section) homeSections.add(section)
} }
} }
}
return homeSections return homeSections
} }
@ -374,6 +371,13 @@ class RealRepository(
return suggestions return suggestions
} }
override suspend fun suggestions(): List<Song> {
if (!PreferenceUtil.homeSuggestions) return listOf<Song>()
return NotPlayedPlaylist().songs().shuffled().takeIf {
it.size > 9
} ?: emptyList()
}
override suspend fun genresHome(): Home { override suspend fun genresHome(): Home {
val genres = genreRepository.genres().shuffled() val genres = genreRepository.genres().shuffled()
return Home(genres, GENRES, R.string.genres) return Home(genres, GENRES, R.string.genres)

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M17.65,6.35c-1.63,-1.63 -3.94,-2.57 -6.48,-2.31 -3.67,0.37 -6.69,3.35 -7.1,7.02C3.52,15.91 7.27,20 12,20c3.19,0 5.93,-1.87 7.21,-4.56 0.32,-0.67 -0.16,-1.44 -0.9,-1.44 -0.37,0 -0.72,0.2 -0.88,0.53 -1.13,2.43 -3.84,3.97 -6.8,3.31 -2.22,-0.49 -4.01,-2.3 -4.48,-4.52C5.31,9.44 8.26,6 12,6c1.66,0 3.14,0.69 4.22,1.78l-1.51,1.51c-0.63,0.63 -0.19,1.71 0.7,1.71H19c0.55,0 1,-0.45 1,-1V6.41c0,-0.89 -1.08,-1.34 -1.71,-0.71l-0.64,0.65z"/>
</vector>

View file

@ -12,7 +12,6 @@
~ See the GNU General Public License for more details. ~ See the GNU General Public License for more details.
--> -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -26,41 +25,13 @@
android:id="@+id/abs_playlists" android:id="@+id/abs_playlists"
layout="@layout/abs_playlists" /> layout="@layout/abs_playlists" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="24dp"
android:gravity="center_horizontal"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="96dp"
android:layout_height="96dp"
app:srcCompat="@drawable/ic_play_arrow_white_64dp"
app:tint="?attr/colorControlNormal" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/emptyText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/start_play_music"
android:textAppearance="@style/TextViewNormal"
android:textColor="?android:attr/textColorPrimary" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<include android:id="@+id/suggestions" layout="@layout/item_suggestions" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView" android:id="@+id/recyclerView"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -76,5 +47,4 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/mini_player_height_expanded" /> android:layout_height="@dimen/mini_player_height_expanded" />
</LinearLayout> </LinearLayout>
</FrameLayout>
</LinearLayout> </LinearLayout>

View file

@ -8,17 +8,27 @@
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/title" android:id="@+id/title"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?rectSelector"
android:padding="16dp" android:padding="16dp"
android:text="@string/suggestion_songs" android:text="@string/suggestion_songs"
android:textAppearance="@style/TextViewHeadline6" android:textAppearance="@style/TextViewHeadline6"
android:textStyle="bold" android:textStyle="bold"
app:layout_constrainedWidth="true" app:layout_constrainedWidth="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<code.name.monkey.retromusic.views.AccentIcon
android:id="@+id/refresh_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
app:layout_constraintBottom_toTopOf="@+id/card7"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="@drawable/round_selector"
app:srcCompat="@drawable/ic_refresh" />
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:id="@+id/card1" android:id="@+id/card1"
@ -142,7 +152,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:autoSizeTextType="uniform" android:autoSizeTextType="uniform"
android:padding="8dp" android:padding="8dp"
android:text="New music mix" android:text="@string/new_music_mix"
android:textAppearance="@style/TextViewNormal" android:textAppearance="@style/TextViewNormal"
android:textSize="32sp" android:textSize="32sp"
android:textStyle="bold" android:textStyle="bold"

View file

@ -364,7 +364,7 @@
<string name="pref_title_colored_app">Adaptive color</string> <string name="pref_title_colored_app">Adaptive color</string>
<string name="pref_title_colored_notification">Colored notification</string> <string name="pref_title_colored_notification">Colored notification</string>
<string name="pref_title_cross_fade">Crossfade (Beta)</string> <string name="pref_title_cross_fade">Crossfade (Beta)</string>
<string name="pref_title_custom_font">Use Custom font</string> <string name="pref_title_custom_font">Use Manrope font</string>
<string name="pref_title_desaturated_color">Desaturated color</string> <string name="pref_title_desaturated_color">Desaturated color</string>
<string name="pref_title_expand_now_playing_panel">Show now playing screen</string> <string name="pref_title_expand_now_playing_panel">Show now playing screen</string>
<string name="pref_title_extra_controls">Extra controls</string> <string name="pref_title_extra_controls">Extra controls</string>
@ -531,4 +531,5 @@
<string name="you_have_to_select_at_least_one_category">You have to select at least one category.</string> <string name="you_have_to_select_at_least_one_category">You have to select at least one category.</string>
<string name="you_will_be_forwarded_to_the_issue_tracker_website">You will be forwarded to the issue tracker website.</string> <string name="you_will_be_forwarded_to_the_issue_tracker_website">You will be forwarded to the issue tracker website.</string>
<string name="your_account_data_is_only_used_for_authentication">Your account data is only used for authentication.</string> <string name="your_account_data_is_only_used_for_authentication">Your account data is only used for authentication.</string>
<string name="new_music_mix">New Music Mix</string>
</resources> </resources>