Item list to support big screen
Fix search for playlist
Fix playlist crash
This commit is contained in:
Hemanth S 2020-09-27 02:09:07 +05:30
parent f2e290d274
commit 209e3d58eb
80 changed files with 1025 additions and 448 deletions

View file

@ -28,16 +28,7 @@ class LockScreenActivity : AbsMusicServiceActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar() setDrawUnderStatusBar()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { lockScreenInit()
setShowWhenLocked(true)
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
keyguardManager.requestDismissKeyguard(this, null)
} else {
this.window.addFlags(
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
)
}
setContentView(R.layout.activity_lock_screen) setContentView(R.layout.activity_lock_screen)
hideStatusBar() hideStatusBar()
setStatusbarColorAuto() setStatusbarColorAuto()
@ -77,6 +68,19 @@ class LockScreenActivity : AbsMusicServiceActivity() {
} }
} }
private fun lockScreenInit() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true)
val keyguardManager: KeyguardManager = getSystemService(KeyguardManager::class.java)
keyguardManager.requestDismissKeyguard(this, null)
} else {
this.window.addFlags(
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
)
}
}
override fun onPlayingMetaChanged() { override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged() super.onPlayingMetaChanged()
updateSongs() updateSongs()

View file

@ -22,6 +22,7 @@ import code.name.monkey.retromusic.util.AppRater
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.android.ext.android.get
class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeListener { class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeListener {
companion object { companion object {
@ -37,6 +38,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar() setDrawUnderStatusBar()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setupNavigationController()
if (!hasPermissions()) { if (!hasPermissions()) {
findNavController(R.id.fragment_container).navigate(R.id.permissionFragment) findNavController(R.id.fragment_container).navigate(R.id.permissionFragment)
} }
@ -49,7 +51,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
updateTabs() updateTabs()
//NavigationUI.setupWithNavController(getBottomNavigationView(), findNavController(R.id.fragment_container)) //NavigationUI.setupWithNavController(getBottomNavigationView(), findNavController(R.id.fragment_container))
setupNavigationController()
} }
private fun setupNavigationController() { private fun setupNavigationController() {
@ -121,8 +123,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
val id = parseLongFromIntent(intent, "playlistId", "playlist") val id = parseLongFromIntent(intent, "playlistId", "playlist")
if (id >= 0L) { if (id >= 0L) {
val position: Int = intent.getIntExtra("position", 0) val position: Int = intent.getIntExtra("position", 0)
val songs: List<Song> = val songs: List<Song> = PlaylistSongsLoader.getPlaylistSongList(get(), id)
PlaylistSongsLoader.getPlaylistSongList(this@MainActivity, id)
MusicPlayerRemote.openQueue(songs, position, true) MusicPlayerRemote.openQueue(songs, position, true)
handled = true handled = true
} }
@ -130,8 +131,9 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
val id = parseLongFromIntent(intent, "albumId", "album") val id = parseLongFromIntent(intent, "albumId", "album")
if (id >= 0L) { if (id >= 0L) {
val position: Int = intent.getIntExtra("position", 0) val position: Int = intent.getIntExtra("position", 0)
val songs = libraryViewModel.albumById(id).songs
MusicPlayerRemote.openQueue( MusicPlayerRemote.openQueue(
libraryViewModel.albumById(id).songs, songs,
position, position,
true true
) )
@ -141,8 +143,9 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
val id = parseLongFromIntent(intent, "artistId", "artist") val id = parseLongFromIntent(intent, "artistId", "artist")
if (id >= 0L) { if (id >= 0L) {
val position: Int = intent.getIntExtra("position", 0) val position: Int = intent.getIntExtra("position", 0)
val songs: List<Song> = libraryViewModel.artistById(id).songs
MusicPlayerRemote.openQueue( MusicPlayerRemote.openQueue(
libraryViewModel.artistById(id).songs, songs,
position, position,
true true
) )

View file

@ -13,7 +13,6 @@ import code.name.monkey.retromusic.adapter.song.PlayingQueueAdapter
import code.name.monkey.retromusic.extensions.accentColor import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.surfaceColor import code.name.monkey.retromusic.extensions.surfaceColor
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.ThemedFastScroller import code.name.monkey.retromusic.util.ThemedFastScroller
import com.h6ah4i.android.widget.advrecyclerview.animator.DraggableItemAnimator import com.h6ah4i.android.widget.advrecyclerview.animator.DraggableItemAnimator
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
@ -21,6 +20,7 @@ import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeMana
import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
import kotlinx.android.synthetic.main.activity_playing_queue.* import kotlinx.android.synthetic.main.activity_playing_queue.*
import kotlinx.android.synthetic.main.activity_playing_queue.title as NoImageTitle
open class PlayingQueueActivity : AbsMusicServiceActivity() { open class PlayingQueueActivity : AbsMusicServiceActivity() {
@ -31,13 +31,6 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() {
private var playingQueueAdapter: PlayingQueueAdapter? = null private var playingQueueAdapter: PlayingQueueAdapter? = null
private lateinit var linearLayoutManager: LinearLayoutManager private lateinit var linearLayoutManager: LinearLayoutManager
private fun getUpNextAndQueueTime(): String {
val duration = MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.position)
return MusicUtil.buildInfoString(
resources.getString(R.string.up_next),
MusicUtil.getReadableDurationString(duration)
)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar() setDrawUnderStatusBar()
@ -54,7 +47,6 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() {
clearQueue.setOnClickListener { clearQueue.setOnClickListener {
MusicPlayerRemote.clearQueue() MusicPlayerRemote.clearQueue()
} }
checkForPadding()
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -107,7 +99,8 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() {
ThemedFastScroller.create(recyclerView) ThemedFastScroller.create(recyclerView)
} }
private fun checkForPadding() { override fun onServiceConnected() {
updateCurrentSong()
} }
override fun onQueueChanged() { override fun onQueueChanged() {
@ -115,7 +108,6 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() {
finish() finish()
return return
} }
checkForPadding()
updateQueue() updateQueue()
updateCurrentSong() updateCurrentSong()
} }
@ -126,7 +118,9 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() {
} }
private fun updateCurrentSong() { private fun updateCurrentSong() {
toolbar.subtitle = getUpNextAndQueueTime() NoImageTitle.text = MusicPlayerRemote.currentSong.title
text.text = MusicPlayerRemote.currentSong.artistName
text2?.text = MusicPlayerRemote.currentSong.albumName
} }
override fun onPlayingMetaChanged() { override fun onPlayingMetaChanged() {
@ -136,7 +130,6 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() {
private fun updateQueuePosition() { private fun updateQueuePosition() {
playingQueueAdapter?.setCurrent(MusicPlayerRemote.position) playingQueueAdapter?.setCurrent(MusicPlayerRemote.position)
resetToCurrentPosition() resetToCurrentPosition()
toolbar.subtitle = getUpNextAndQueueTime()
} }
private fun updateQueue() { private fun updateQueue() {
@ -174,7 +167,6 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() {
} }
private fun setupToolbar() { private fun setupToolbar() {
toolbar.subtitle = getUpNextAndQueueTime()
toolbar.setBackgroundColor(surfaceColor()) toolbar.setBackgroundColor(surfaceColor())
setSupportActionBar(toolbar) setSupportActionBar(toolbar)
clearQueue.backgroundTintList = ColorStateList.valueOf(accentColor()) clearQueue.backgroundTintList = ColorStateList.valueOf(accentColor())

View file

@ -1,6 +1,5 @@
package code.name.monkey.retromusic.adapter package code.name.monkey.retromusic.adapter
import android.graphics.Color
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -23,14 +22,12 @@ class GenreAdapter(
var dataSet: List<Genre>, var dataSet: List<Genre>,
private val mItemLayoutRes: Int private val mItemLayoutRes: Int
) : RecyclerView.Adapter<GenreAdapter.ViewHolder>() { ) : RecyclerView.Adapter<GenreAdapter.ViewHolder>() {
val colors = listOf<Int>(Color.RED, Color.BLUE)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(activity).inflate(mItemLayoutRes, parent, false)) return ViewHolder(LayoutInflater.from(activity).inflate(mItemLayoutRes, parent, false))
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val genre = dataSet[position] val genre = dataSet[position]
holder.title?.text = genre.name holder.title?.text = genre.name
holder.text?.text = String.format( holder.text?.text = String.format(
Locale.getDefault(), Locale.getDefault(),

View file

@ -4,12 +4,15 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.glide.AlbumGlideRequest import code.name.monkey.retromusic.glide.AlbumGlideRequest
import code.name.monkey.retromusic.glide.ArtistGlideRequest import code.name.monkey.retromusic.glide.ArtistGlideRequest
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
@ -19,6 +22,7 @@ import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist
import code.name.monkey.retromusic.repository.PlaylistSongsLoader import code.name.monkey.retromusic.repository.PlaylistSongsLoader
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import java.util.*
class SearchAdapter( class SearchAdapter(
private val activity: FragmentActivity, private val activity: FragmentActivity,
@ -34,7 +38,7 @@ class SearchAdapter(
if (dataSet[position] is Album) return ALBUM if (dataSet[position] is Album) return ALBUM
if (dataSet[position] is Artist) return ARTIST if (dataSet[position] is Artist) return ARTIST
if (dataSet[position] is Genre) return GENRE if (dataSet[position] is Genre) return GENRE
if (dataSet[position] is Playlist) return PLAYLIST if (dataSet[position] is PlaylistWithSongs) return PLAYLIST
return if (dataSet[position] is Song) SONG else HEADER return if (dataSet[position] is Song) SONG else HEADER
} }
@ -56,42 +60,52 @@ class SearchAdapter(
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
when (getItemViewType(position)) { when (getItemViewType(position)) {
ALBUM -> { ALBUM -> {
val album = dataSet.get(position) as Album holder. imageTextContainer?.isVisible = true
val album = dataSet[position] as Album
holder.title?.text = album.title holder.title?.text = album.title
holder.text?.text = album.artistName holder.text?.text = album.artistName
AlbumGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong()) AlbumGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
.checkIgnoreMediaStore().build().into(holder.image) .checkIgnoreMediaStore().build().into(holder.image)
} }
ARTIST -> { ARTIST -> {
val artist = dataSet.get(position) as Artist holder. imageTextContainer?.isVisible = true
val artist = dataSet[position] as Artist
holder.title?.text = artist.name holder.title?.text = artist.name
holder.text?.text = MusicUtil.getArtistInfoString(activity, artist) holder.text?.text = MusicUtil.getArtistInfoString(activity, artist)
ArtistGlideRequest.Builder.from(Glide.with(activity), artist).build() ArtistGlideRequest.Builder.from(Glide.with(activity), artist).build()
.into(holder.image) .into(holder.image)
} }
SONG -> { SONG -> {
val song = dataSet.get(position) as Song val song = dataSet[position] as Song
holder.title?.text = song.title holder.title?.text = song.title
holder.text?.text = song.albumName holder.text?.text = song.albumName
} }
GENRE -> { GENRE -> {
val genre = dataSet.get(position) as Genre val genre = dataSet[position] as Genre
holder.title?.text = genre.name holder.title?.text = genre.name
holder.text?.text = String.format(
Locale.getDefault(),
"%d %s",
genre.songCount,
if (genre.songCount > 1) activity.getString(R.string.songs) else activity.getString(
R.string.song
)
)
} }
PLAYLIST -> { PLAYLIST -> {
val playlist = dataSet.get(position) as Playlist val playlist = dataSet[position] as PlaylistWithSongs
holder.title?.text = playlist.name holder.title?.text = playlist.playlistEntity.playlistName
holder.text?.text = MusicUtil.getPlaylistInfoString(activity, getSongs(playlist)) holder.text?.text = MusicUtil.playlistInfoString(activity, playlist.songs)
} }
else -> { else -> {
holder.title?.text = dataSet.get(position).toString() holder.title?.text = dataSet[position].toString()
holder.title?.setTextColor(ThemeStore.accentColor(activity)) holder.title?.setTextColor(ThemeStore.accentColor(activity))
} }
} }
} }
private fun getSongs(playlist: Playlist): java.util.ArrayList<Song> { private fun getSongs(playlist: Playlist): List<Song> {
val songs = java.util.ArrayList<Song>() val songs = mutableListOf<Song>()
if (playlist is AbsSmartPlaylist) { if (playlist is AbsSmartPlaylist) {
songs.addAll(playlist.getSongs()) songs.addAll(playlist.getSongs())
} else { } else {
@ -107,7 +121,7 @@ class SearchAdapter(
inner class ViewHolder(itemView: View, itemViewType: Int) : MediaEntryViewHolder(itemView) { inner class ViewHolder(itemView: View, itemViewType: Int) : MediaEntryViewHolder(itemView) {
init { init {
itemView.setOnLongClickListener(null) itemView.setOnLongClickListener(null)
imageTextContainer?.isInvisible = true
if (itemViewType == SONG) { if (itemViewType == SONG) {
menu?.visibility = View.VISIBLE menu?.visibility = View.VISIBLE
menu?.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) { menu?.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
@ -156,7 +170,7 @@ class SearchAdapter(
) )
} }
SONG -> { SONG -> {
val playList = ArrayList<Song>() val playList = mutableListOf<Song>()
playList.add(item as Song) playList.add(item as Song)
MusicPlayerRemote.openQueue(playList, 0, true) MusicPlayerRemote.openQueue(playList, 0, true)
} }

View file

@ -16,7 +16,6 @@ package code.name.monkey.retromusic.adapter.base;
import android.graphics.Color; import android.graphics.Color;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
@ -41,15 +40,13 @@ public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHold
@Nullable @Nullable
public ImageView image; public ImageView image;
@Nullable @Nullable
public ImageView artistImage; public ImageView artistImage;
@Nullable @Nullable
public ImageView playerImage; public ImageView playerImage;
@Nullable
public ViewGroup imageContainer;
@Nullable @Nullable
public MaterialCardView imageContainerCard; public MaterialCardView imageContainerCard;
@ -77,6 +74,9 @@ public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHold
@Nullable @Nullable
public TextView text; public TextView text;
@Nullable
public TextView text2;
@Nullable @Nullable
public TextView time; public TextView time;
@ -87,6 +87,7 @@ public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHold
super(itemView); super(itemView);
title = itemView.findViewById(R.id.title); title = itemView.findViewById(R.id.title);
text = itemView.findViewById(R.id.text); text = itemView.findViewById(R.id.text);
text2 = itemView.findViewById(R.id.text2);
image = itemView.findViewById(R.id.image); image = itemView.findViewById(R.id.image);
artistImage = itemView.findViewById(R.id.artistImage); artistImage = itemView.findViewById(R.id.artistImage);
@ -94,7 +95,6 @@ public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHold
time = itemView.findViewById(R.id.time); time = itemView.findViewById(R.id.time);
imageText = itemView.findViewById(R.id.imageText); imageText = itemView.findViewById(R.id.imageText);
imageContainer = itemView.findViewById(R.id.imageContainer);
imageTextContainer = itemView.findViewById(R.id.imageTextContainer); imageTextContainer = itemView.findViewById(R.id.imageTextContainer);
imageContainerCard = itemView.findViewById(R.id.imageContainerCard); imageContainerCard = itemView.findViewById(R.id.imageContainerCard);

View file

@ -4,14 +4,14 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.ICabHolder import code.name.monkey.retromusic.interfaces.ICabHolder
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
abstract class AbsOffsetSongAdapter( abstract class AbsOffsetSongAdapter(
activity: AppCompatActivity, activity: FragmentActivity,
dataSet: MutableList<Song>, dataSet: MutableList<Song>,
@LayoutRes itemLayoutRes: Int, @LayoutRes itemLayoutRes: Int,
ICabHolder: ICabHolder? ICabHolder: ICabHolder?

View file

@ -173,7 +173,7 @@ class PlayingQueueAdapter(
} }
override fun onGetSwipeReactionType(holder: ViewHolder, position: Int, x: Int, y: Int): Int { override fun onGetSwipeReactionType(holder: ViewHolder, position: Int, x: Int, y: Int): Int {
return if (onCheckCanStartDrag(holder!!, position, x, y)) { return if (onCheckCanStartDrag(holder, position, x, y)) {
SwipeableItemConstants.REACTION_CAN_NOT_SWIPE_BOTH_H SwipeableItemConstants.REACTION_CAN_NOT_SWIPE_BOTH_H
} else { } else {
SwipeableItemConstants.REACTION_CAN_SWIPE_BOTH_H SwipeableItemConstants.REACTION_CAN_SWIPE_BOTH_H

View file

@ -2,22 +2,21 @@ package code.name.monkey.retromusic.adapter.song
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import androidx.core.os.bundleOf
import androidx.navigation.findNavController
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.db.PlaylistEntity
import code.name.monkey.retromusic.db.toSongEntity
import code.name.monkey.retromusic.dialogs.RemoveSongFromPlaylistDialog
import code.name.monkey.retromusic.interfaces.ICabHolder import code.name.monkey.retromusic.interfaces.ICabHolder
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import com.google.android.material.button.MaterialButton
open class PlaylistSongAdapter( open class PlaylistSongAdapter(
activity: AppCompatActivity, private val playlist: PlaylistEntity,
activity: FragmentActivity,
dataSet: MutableList<Song>, dataSet: MutableList<Song>,
itemLayoutRes: Int, itemLayoutRes: Int,
ICabHolder: ICabHolder? ICabHolder: ICabHolder?
) : AbsOffsetSongAdapter(activity, dataSet, itemLayoutRes, ICabHolder) { ) : SongAdapter(activity, dataSet, itemLayoutRes, ICabHolder) {
init { init {
this.setMultiSelectMenuRes(R.menu.menu_cannot_delete_single_songs_playlist_songs_selection) this.setMultiSelectMenuRes(R.menu.menu_cannot_delete_single_songs_playlist_songs_selection)
@ -27,44 +26,22 @@ open class PlaylistSongAdapter(
return ViewHolder(view) return ViewHolder(view)
} }
override fun onBindViewHolder(holder: SongAdapter.ViewHolder, position: Int) { open inner class ViewHolder(itemView: View) : SongAdapter.ViewHolder(itemView) {
if (holder.itemViewType == OFFSET_ITEM) {
val viewHolder = holder as ViewHolder
viewHolder.playAction?.let {
it.setOnClickListener {
MusicPlayerRemote.openQueue(dataSet, 0, true)
}
}
viewHolder.shuffleAction?.let {
it.setOnClickListener {
MusicPlayerRemote.openAndShuffleQueue(dataSet, true)
}
}
} else {
super.onBindViewHolder(holder, position - 1)
}
}
open inner class ViewHolder(itemView: View) : AbsOffsetSongAdapter.ViewHolder(itemView) {
val playAction: MaterialButton? = itemView.findViewById(R.id.playAction)
val shuffleAction: MaterialButton? = itemView.findViewById(R.id.shuffleAction)
override var songMenuRes: Int override var songMenuRes: Int
get() = R.menu.menu_item_cannot_delete_single_songs_playlist_song get() = R.menu.menu_item_playlist_song
set(value) { set(value) {
super.songMenuRes = value super.songMenuRes = value
} }
override fun onSongMenuItemClick(item: MenuItem): Boolean { override fun onSongMenuItemClick(item: MenuItem): Boolean {
if (item.itemId == R.id.action_go_to_album) { when (item.itemId) {
activity.findNavController(R.id.fragment_container) R.id.action_remove_from_playlist -> {
.navigate( RemoveSongFromPlaylistDialog.create(song.toSongEntity(playlist.playListId))
R.id.albumDetailsFragment, .show(activity.supportFragmentManager, "REMOVE_FROM_PLAYLIST")
bundleOf(EXTRA_ALBUM_ID to song.albumId)
)
return true return true
} }
}
return super.onSongMenuItemClick(item) return super.onSongMenuItemClick(item)
} }
} }

View file

@ -7,6 +7,7 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController import androidx.navigation.findNavController
import code.name.monkey.retromusic.EXTRA_ALBUM_ID import code.name.monkey.retromusic.EXTRA_ALBUM_ID
@ -87,6 +88,7 @@ open class SongAdapter(
} }
holder.title?.text = getSongTitle(song) holder.title?.text = getSongTitle(song)
holder.text?.text = getSongText(song) holder.text?.text = getSongText(song)
holder.text2?.text = getSongText(song)
loadAlbumCover(song, holder) loadAlbumCover(song, holder)
} }
@ -121,6 +123,10 @@ open class SongAdapter(
return song.artistName return song.artistName
} }
private fun getSongText2(song: Song): String? {
return song.albumName
}
override fun getItemCount(): Int { override fun getItemCount(): Int {
return dataSet.size return dataSet.size
} }
@ -172,7 +178,7 @@ open class SongAdapter(
} }
protected open fun onSongMenuItemClick(item: MenuItem): Boolean { protected open fun onSongMenuItemClick(item: MenuItem): Boolean {
if (image != null && image!!.visibility == View.VISIBLE) { if (image != null && image!!.isVisible) {
when (item.itemId) { when (item.itemId) {
R.id.action_go_to_album -> { R.id.action_go_to_album -> {
activity.findNavController(R.id.fragment_container) activity.findNavController(R.id.fragment_container)

View file

@ -2,6 +2,12 @@ package code.name.monkey.retromusic.db
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
fun List<HistoryEntity>.fromHistoryToSongs(): List<Song> {
return map {
it.toSong()
}
}
fun List<SongEntity>.toSongs(): List<Song> { fun List<SongEntity>.toSongs(): List<Song> {
return map { return map {
it.toSong() it.toSong()
@ -131,3 +137,4 @@ fun List<Song>.toSongsEntity(playlistEntity: PlaylistEntity): List<SongEntity> {
it.toSongEntity(playlistEntity.playListId) it.toSongEntity(playlistEntity.playListId)
} }
} }

View file

@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.lifecycle.Observer
import androidx.navigation.fragment.FragmentNavigatorExtras import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
@ -23,13 +22,12 @@ import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.state.NowPlayingPanelState import code.name.monkey.retromusic.state.NowPlayingPanelState
import code.name.monkey.retromusic.util.RetroUtil
import kotlinx.android.synthetic.main.fragment_playlist_detail.* import kotlinx.android.synthetic.main.fragment_playlist_detail.*
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_detail), class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_detail),
ArtistClickListener, AlbumClickListener { ArtistClickListener, AlbumClickListener {
private val args by navArgs<DetailListFragmentArgs>() private val args by navArgs<DetailListFragmentArgs>()
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
@ -55,7 +53,6 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
TOP_PLAYED_PLAYLIST -> topPlayed() TOP_PLAYED_PLAYLIST -> topPlayed()
} }
recyclerView.adapter?.registerAdapterDataObserver(object : AdapterDataObserver() { recyclerView.adapter?.registerAdapterDataObserver(object : AdapterDataObserver() {
override fun onChanged() { override fun onChanged() {
super.onChanged() super.onChanged()
@ -76,7 +73,7 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
adapter = songAdapter adapter = songAdapter
layoutManager = linearLayoutManager() layoutManager = linearLayoutManager()
} }
libraryViewModel.recentSongs().observe(viewLifecycleOwner, Observer { songs -> libraryViewModel.recentSongs().observe(viewLifecycleOwner, { songs ->
songAdapter.swapDataSet(songs) songAdapter.swapDataSet(songs)
}) })
} }
@ -92,7 +89,7 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
adapter = songAdapter adapter = songAdapter
layoutManager = linearLayoutManager() layoutManager = linearLayoutManager()
} }
libraryViewModel.playCountSongs().observe(viewLifecycleOwner, Observer { songs -> libraryViewModel.playCountSongs().observe(viewLifecycleOwner, { songs ->
songAdapter.swapDataSet(songs) songAdapter.swapDataSet(songs)
}) })
} }
@ -109,9 +106,8 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
adapter = songAdapter adapter = songAdapter
layoutManager = linearLayoutManager() layoutManager = linearLayoutManager()
} }
libraryViewModel.observableHistorySongs().observe(viewLifecycleOwner, Observer { libraryViewModel.observableHistorySongs().observe(viewLifecycleOwner, {
val songs = it.map { historyEntity -> historyEntity.toSong() } songAdapter.swapDataSet(it)
songAdapter.swapDataSet(songs)
}) })
} }
@ -170,8 +166,14 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
private fun gridLayoutManager(): GridLayoutManager = private fun gridLayoutManager(): GridLayoutManager =
GridLayoutManager(requireContext(), 2, GridLayoutManager.VERTICAL, false) GridLayoutManager(requireContext(), gridCount(), GridLayoutManager.VERTICAL, false)
private fun gridCount(): Int {
if (RetroUtil.isTablet()) {
return if (RetroUtil.isLandscape()) 6 else 4
}
return 2
}
override fun onArtist(artistId: Long, imageView: ImageView) { override fun onArtist(artistId: Long, imageView: ImageView) {
findNavController().navigate( findNavController().navigate(

View file

@ -11,11 +11,8 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener
import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.model.*
import code.name.monkey.retromusic.repository.RealRepository import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.state.NowPlayingPanelState import code.name.monkey.retromusic.state.NowPlayingPanelState
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -39,6 +36,10 @@ class LibraryViewModel(
panelState.postValue(state) panelState.postValue(state)
} }
init {
loadLibraryContent()
}
private fun loadLibraryContent() = viewModelScope.launch(IO) { private fun loadLibraryContent() = viewModelScope.launch(IO) {
fetchHomeSections() fetchHomeSections()
fetchSongs() fetchSongs()
@ -51,37 +52,30 @@ class LibraryViewModel(
fun getSearchResult(): LiveData<List<Any>> = searchResults fun getSearchResult(): LiveData<List<Any>> = searchResults
fun getSongs(): LiveData<List<Song>> { fun getSongs(): LiveData<List<Song>> {
fetchSongs()
return songs return songs
} }
fun getAlbums(): LiveData<List<Album>> { fun getAlbums(): LiveData<List<Album>> {
fetchAlbums()
return albums return albums
} }
fun getArtists(): LiveData<List<Artist>> { fun getArtists(): LiveData<List<Artist>> {
fetchArtists()
return artists return artists
} }
fun getPlaylists(): LiveData<List<PlaylistWithSongs>> { fun getPlaylists(): LiveData<List<PlaylistWithSongs>> {
fetchPlaylists()
return playlists return playlists
} }
fun getLegacyPlaylist(): LiveData<List<Playlist>> { fun getLegacyPlaylist(): LiveData<List<Playlist>> {
fetchLegacyPlaylist()
return legacyPlaylists return legacyPlaylists
} }
fun getGenre(): LiveData<List<Genre>> { fun getGenre(): LiveData<List<Genre>> {
fetchGenres()
return genres return genres
} }
fun getHome(): LiveData<List<Home>> { fun getHome(): LiveData<List<Home>> {
fetchHomeSections()
return home return home
} }
@ -261,10 +255,6 @@ class LibraryViewModel(
}) })
} }
fun observableHistorySongs() = repository.observableHistorySongs()
fun favorites() = repository.favorites()
fun artists(type: Int): LiveData<List<Artist>> = liveData { fun artists(type: Int): LiveData<List<Artist>> = liveData {
when (type) { when (type) {
TOP_ARTISTS -> emit(repository.topArtists()) TOP_ARTISTS -> emit(repository.topArtists())
@ -283,12 +273,6 @@ class LibraryViewModel(
} }
} }
fun clearSearchResult() {
viewModelScope.launch {
searchResults.postValue(emptyList())
}
}
fun artist(artistId: Long): LiveData<Artist> = liveData { fun artist(artistId: Long): LiveData<Artist> = liveData {
emit(repository.artistById(artistId)) emit(repository.artistById(artistId))
} }
@ -296,6 +280,16 @@ class LibraryViewModel(
fun fetchContributors(): LiveData<List<Contributor>> = liveData { fun fetchContributors(): LiveData<List<Contributor>> = liveData {
emit(repository.contributor()) emit(repository.contributor())
} }
fun observableHistorySongs() = repository.observableHistorySongs()
fun favorites() = repository.favorites()
fun clearSearchResult() {
viewModelScope.launch {
searchResults.postValue(emptyList())
}
}
} }
enum class ReloadType { enum class ReloadType {

View file

@ -30,7 +30,6 @@ import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
import code.name.monkey.retromusic.extensions.applyColor import code.name.monkey.retromusic.extensions.applyColor
import code.name.monkey.retromusic.extensions.applyOutlineColor import code.name.monkey.retromusic.extensions.applyOutlineColor
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.glide.AlbumGlideRequest import code.name.monkey.retromusic.glide.AlbumGlideRequest
import code.name.monkey.retromusic.glide.ArtistGlideRequest import code.name.monkey.retromusic.glide.ArtistGlideRequest
@ -57,7 +56,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koin.android.ext.android.get import org.koin.android.ext.android.get
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf import org.koin.core.parameter.parametersOf
import java.util.* import java.util.*
@ -69,7 +67,6 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
private val detailsViewModel by viewModel<AlbumDetailsViewModel> { private val detailsViewModel by viewModel<AlbumDetailsViewModel> {
parametersOf(arguments.extraAlbumId) parametersOf(arguments.extraAlbumId)
} }
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
private lateinit var simpleSongAdapter: SimpleSongAdapter private lateinit var simpleSongAdapter: SimpleSongAdapter
private lateinit var album: Album private lateinit var album: Album

View file

@ -26,7 +26,6 @@ import code.name.monkey.retromusic.extensions.applyColor
import code.name.monkey.retromusic.extensions.applyOutlineColor import code.name.monkey.retromusic.extensions.applyOutlineColor
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.extensions.showToast import code.name.monkey.retromusic.extensions.showToast
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.albums.AlbumClickListener import code.name.monkey.retromusic.fragments.albums.AlbumClickListener
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.glide.ArtistGlideRequest import code.name.monkey.retromusic.glide.ArtistGlideRequest
@ -47,7 +46,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koin.android.ext.android.get import org.koin.android.ext.android.get
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf import org.koin.core.parameter.parametersOf
import java.util.* import java.util.*
@ -59,7 +57,6 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d
private val detailsViewModel: ArtistDetailsViewModel by viewModel { private val detailsViewModel: ArtistDetailsViewModel by viewModel {
parametersOf(arguments.extraArtistId) parametersOf(arguments.extraArtistId)
} }
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
private lateinit var artist: Artist private lateinit var artist: Artist
private lateinit var songAdapter: SimpleSongAdapter private lateinit var songAdapter: SimpleSongAdapter
private lateinit var albumAdapter: HorizontalAlbumAdapter private lateinit var albumAdapter: HorizontalAlbumAdapter

View file

@ -8,8 +8,11 @@ import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.MainActivity import code.name.monkey.retromusic.activities.MainActivity
import code.name.monkey.retromusic.fragments.LibraryViewModel
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
abstract class AbsMainActivityFragment(@LayoutRes layout: Int) : AbsMusicServiceFragment(layout) { abstract class AbsMainActivityFragment(@LayoutRes layout: Int) : AbsMusicServiceFragment(layout) {
val libraryViewModel: LibraryViewModel by sharedViewModel()
val mainActivity: MainActivity val mainActivity: MainActivity
get() = activity as MainActivity get() = activity as MainActivity

View file

@ -27,7 +27,6 @@ import code.name.monkey.retromusic.db.toSongEntity
import code.name.monkey.retromusic.dialogs.* import code.name.monkey.retromusic.dialogs.*
import code.name.monkey.retromusic.extensions.hide import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.whichFragment import code.name.monkey.retromusic.extensions.whichFragment
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.ReloadType import code.name.monkey.retromusic.fragments.ReloadType
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
@ -43,14 +42,12 @@ import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koin.android.ext.android.get import org.koin.android.ext.android.get
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import java.io.FileNotFoundException import java.io.FileNotFoundException
abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragment(layout), abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragment(layout),
Toolbar.OnMenuItemClickListener, IPaletteColorHolder, PlayerAlbumCoverFragment.Callbacks { Toolbar.OnMenuItemClickListener, IPaletteColorHolder, PlayerAlbumCoverFragment.Callbacks {
private var playerAlbumCoverFragment: PlayerAlbumCoverFragment? = null private var playerAlbumCoverFragment: PlayerAlbumCoverFragment? = null
protected val libraryViewModel by sharedViewModel<LibraryViewModel>()
override fun onMenuItemClick( override fun onMenuItemClick(
item: MenuItem item: MenuItem

View file

@ -13,7 +13,6 @@ import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog
import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.state.NowPlayingPanelState import code.name.monkey.retromusic.state.NowPlayingPanelState
import code.name.monkey.retromusic.util.DensityUtil import code.name.monkey.retromusic.util.DensityUtil
@ -23,15 +22,12 @@ import com.google.android.material.appbar.AppBarLayout
import kotlinx.android.synthetic.main.fragment_main_recycler.* import kotlinx.android.synthetic.main.fragment_main_recycler.*
import me.zhanghai.android.fastscroll.FastScroller import me.zhanghai.android.fastscroll.FastScroller
import me.zhanghai.android.fastscroll.FastScrollerBuilder import me.zhanghai.android.fastscroll.FastScrollerBuilder
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : RecyclerView.LayoutManager> : abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : RecyclerView.LayoutManager> :
AbsMainActivityFragment(R.layout.fragment_main_recycler), AbsMainActivityFragment(R.layout.fragment_main_recycler),
AppBarLayout.OnOffsetChangedListener { AppBarLayout.OnOffsetChangedListener {
val libraryViewModel: LibraryViewModel by sharedViewModel()
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true) setHasOptionsMenu(true)

View file

@ -75,6 +75,7 @@ import code.name.monkey.retromusic.misc.DialogAsyncTask;
import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener; import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener;
import code.name.monkey.retromusic.misc.WrappedAsyncTaskLoader; import code.name.monkey.retromusic.misc.WrappedAsyncTaskLoader;
import code.name.monkey.retromusic.model.Song; import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.state.NowPlayingPanelState;
import code.name.monkey.retromusic.util.DensityUtil; import code.name.monkey.retromusic.util.DensityUtil;
import code.name.monkey.retromusic.util.FileUtil; import code.name.monkey.retromusic.util.FileUtil;
import code.name.monkey.retromusic.util.PreferenceUtil; import code.name.monkey.retromusic.util.PreferenceUtil;
@ -163,6 +164,7 @@ public class FoldersFragment extends AbsMainActivityFragment implements
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
getLibraryViewModel().setPanelState(NowPlayingPanelState.COLLAPSED_WITH);
getMainActivity().setSupportActionBar(toolbar); getMainActivity().setSupportActionBar(toolbar);
getMainActivity().getSupportActionBar().setTitle(null); getMainActivity().getSupportActionBar().setTitle(null);
setStatusBarColorAuto(view); setStatusBarColorAuto(view);

View file

@ -12,14 +12,12 @@ import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.song.SongAdapter import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.extensions.dipToPix import code.name.monkey.retromusic.extensions.dipToPix
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.helper.menu.GenreMenuHelper import code.name.monkey.retromusic.helper.menu.GenreMenuHelper
import code.name.monkey.retromusic.model.Genre import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.state.NowPlayingPanelState import code.name.monkey.retromusic.state.NowPlayingPanelState
import kotlinx.android.synthetic.main.fragment_playlist_detail.* import kotlinx.android.synthetic.main.fragment_playlist_detail.*
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf import org.koin.core.parameter.parametersOf
import java.util.* import java.util.*
@ -29,7 +27,6 @@ class GenreDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playlist_
private val detailsViewModel: GenreDetailsViewModel by viewModel { private val detailsViewModel: GenreDetailsViewModel by viewModel {
parametersOf(arguments.extraGenre) parametersOf(arguments.extraGenre)
} }
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
private lateinit var genre: Genre private lateinit var genre: Genre
private lateinit var songAdapter: SongAdapter private lateinit var songAdapter: SongAdapter

View file

@ -37,24 +37,23 @@ import code.name.monkey.retromusic.adapter.HomeAdapter
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog
import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog
import code.name.monkey.retromusic.extensions.findActivityNavController import code.name.monkey.retromusic.extensions.findActivityNavController
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.glide.ProfileBannerGlideRequest import code.name.monkey.retromusic.glide.ProfileBannerGlideRequest
import code.name.monkey.retromusic.glide.UserProfileGlideRequest import code.name.monkey.retromusic.glide.UserProfileGlideRequest
import code.name.monkey.retromusic.state.NowPlayingPanelState
import code.name.monkey.retromusic.util.NavigationUtil import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.abs_playlists.* import kotlinx.android.synthetic.main.abs_playlists.*
import kotlinx.android.synthetic.main.fragment_banner_home.* import kotlinx.android.synthetic.main.fragment_banner_home.*
import kotlinx.android.synthetic.main.home_content.* import kotlinx.android.synthetic.main.home_content.*
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
class HomeFragment : class HomeFragment :
AbsMainActivityFragment(if (PreferenceUtil.isHomeBanner) R.layout.fragment_banner_home else R.layout.fragment_home) { AbsMainActivityFragment(if (PreferenceUtil.isHomeBanner) R.layout.fragment_banner_home else R.layout.fragment_home) {
private val libraryViewModel: LibraryViewModel by sharedViewModel()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
libraryViewModel.setPanelState(NowPlayingPanelState.COLLAPSED_WITH)
mainActivity.setSupportActionBar(toolbar) mainActivity.setSupportActionBar(toolbar)
mainActivity.supportActionBar?.title = null mainActivity.supportActionBar?.title = null
setStatusBarColorAuto(view) setStatusBarColorAuto(view)

View file

@ -15,18 +15,14 @@ import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog
import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog
import code.name.monkey.retromusic.extensions.whichFragment import code.name.monkey.retromusic.extensions.whichFragment
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.model.CategoryInfo import code.name.monkey.retromusic.model.CategoryInfo
import code.name.monkey.retromusic.state.NowPlayingPanelState import code.name.monkey.retromusic.state.NowPlayingPanelState
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import kotlinx.android.synthetic.main.fragment_library.* import kotlinx.android.synthetic.main.fragment_library.*
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) { class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true) setHasOptionsMenu(true)

View file

@ -5,26 +5,20 @@ import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.core.view.isVisible
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter import code.name.monkey.retromusic.adapter.song.PlaylistSongAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.db.PlaylistWithSongs import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.db.toSongs import code.name.monkey.retromusic.db.toSongs
import code.name.monkey.retromusic.extensions.dipToPix import code.name.monkey.retromusic.extensions.dipToPix
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.state.NowPlayingPanelState import code.name.monkey.retromusic.state.NowPlayingPanelState
import code.name.monkey.retromusic.util.PlaylistsUtil
import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
import kotlinx.android.synthetic.main.fragment_playlist_detail.* import kotlinx.android.synthetic.main.fragment_playlist_detail.*
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf import org.koin.core.parameter.parametersOf
@ -33,12 +27,9 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
private val viewModel: PlaylistDetailsViewModel by viewModel { private val viewModel: PlaylistDetailsViewModel by viewModel {
parametersOf(arguments.extraPlaylist) parametersOf(arguments.extraPlaylist)
} }
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
private lateinit var playlist: PlaylistWithSongs
private lateinit var adapter: SongAdapter
private var wrappedAdapter: RecyclerView.Adapter<*>? = null private lateinit var playlist: PlaylistWithSongs
private var recyclerViewDragDropManager: RecyclerViewDragDropManager? = null private lateinit var playlistSongAdapter: PlaylistSongAdapter
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
@ -58,39 +49,19 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
} }
private fun setUpRecyclerView() { private fun setUpRecyclerView() {
recyclerView.layoutManager = LinearLayoutManager(requireContext()) playlistSongAdapter = PlaylistSongAdapter(
recyclerViewDragDropManager = RecyclerViewDragDropManager()
val animator = RefactoredDefaultItemAnimator()
adapter =
OrderablePlaylistSongAdapter(
playlist.playlistEntity, playlist.playlistEntity,
requireActivity(), requireActivity(),
ArrayList(), ArrayList(),
R.layout.item_list, R.layout.item_list,
null, null,
object : OrderablePlaylistSongAdapter.OnMoveItemListener {
override fun onMoveItem(fromPosition: Int, toPosition: Int) {
if (PlaylistsUtil.moveItem(
requireContext(),
playlist.playlistEntity.playListId,
fromPosition,
toPosition
) )
) { recyclerView.apply {
val song = adapter.dataSet.removeAt(fromPosition) layoutManager = LinearLayoutManager(requireContext())
adapter.dataSet.add(toPosition, song) adapter = playlistSongAdapter
adapter.notifyItemMoved(fromPosition, toPosition)
} }
} playlistSongAdapter.registerAdapterDataObserver(object :
}) RecyclerView.AdapterDataObserver() {
wrappedAdapter = recyclerViewDragDropManager!!.createWrappedAdapter(adapter)
recyclerView.adapter = wrappedAdapter
recyclerView.itemAnimator = animator
recyclerViewDragDropManager?.attachRecyclerView(recyclerView)
adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() { override fun onChanged() {
super.onChanged() super.onChanged()
checkIsEmpty() checkIsEmpty()
@ -100,10 +71,7 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater) super.onCreateOptionsMenu(menu, inflater)
val menuRes =/* if (playlist is AbsCustomPlaylist) inflater.inflate(R.menu.menu_playlist_detail, menu)
R.menu.menu_smart_playlist_detail
else*/ R.menu.menu_playlist_detail
inflater.inflate(menuRes, menu)
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -117,32 +85,14 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
private fun checkIsEmpty() { private fun checkIsEmpty() {
checkForPadding() checkForPadding()
empty.visibility = if (adapter.itemCount == 0) View.VISIBLE else View.GONE empty.isVisible = playlistSongAdapter.itemCount == 0
emptyText.visibility = if (adapter.itemCount == 0) View.VISIBLE else View.GONE emptyText.isVisible = playlistSongAdapter.itemCount == 0
} }
override fun onPause() {
if (recyclerViewDragDropManager != null) {
recyclerViewDragDropManager!!.cancelDrag()
}
super.onPause()
}
override fun onDestroy() { override fun onDestroy() {
if (recyclerViewDragDropManager != null) { recyclerView?.itemAnimator = null
recyclerViewDragDropManager!!.release() recyclerView?.adapter = null
recyclerViewDragDropManager = null
}
if (recyclerView != null) {
recyclerView!!.itemAnimator = null
recyclerView!!.adapter = null
}
if (wrappedAdapter != null) {
WrapperAdapterUtils.releaseAll(wrappedAdapter)
wrappedAdapter = null
}
super.onDestroy() super.onDestroy()
} }
@ -154,7 +104,7 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
fun songs(songs: List<Song>) { fun songs(songs: List<Song>) {
progressIndicator.hide() progressIndicator.hide()
if (songs.isNotEmpty()) { if (songs.isNotEmpty()) {
adapter.swapDataSet(songs) playlistSongAdapter.swapDataSet(songs)
} else { } else {
showEmptyView() showEmptyView()
} }

View file

@ -20,12 +20,10 @@ import code.name.monkey.retromusic.adapter.SearchAdapter
import code.name.monkey.retromusic.extensions.accentColor import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.dipToPix import code.name.monkey.retromusic.extensions.dipToPix
import code.name.monkey.retromusic.extensions.showToast import code.name.monkey.retromusic.extensions.showToast
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.state.NowPlayingPanelState import code.name.monkey.retromusic.state.NowPlayingPanelState
import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputEditText
import kotlinx.android.synthetic.main.fragment_search.* import kotlinx.android.synthetic.main.fragment_search.*
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@ -35,7 +33,6 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
const val REQ_CODE_SPEECH_INPUT = 9001 const val REQ_CODE_SPEECH_INPUT = 9001
} }
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
private lateinit var searchAdapter: SearchAdapter private lateinit var searchAdapter: SearchAdapter
private var query: String? = null private var query: String? = null

View file

@ -33,7 +33,7 @@ class PlaylistSong(
override val artistName: String, override val artistName: String,
val playlistId: Long, val playlistId: Long,
val idInPlayList: Long, val idInPlayList: Long,
override val composer: String, override val composer: String?,
override val albumArtist: String? override val albumArtist: String?
) : Song( ) : Song(
id = id, id = id,

View file

@ -16,9 +16,8 @@ package code.name.monkey.retromusic.repository
import android.content.Context import android.content.Context
import android.database.Cursor import android.database.Cursor
import android.provider.MediaStore
import android.provider.MediaStore.Audio.AudioColumns import android.provider.MediaStore.Audio.AudioColumns
import android.provider.MediaStore.Audio.Playlists.* import android.provider.MediaStore.Audio.Playlists.Members
import code.name.monkey.retromusic.Constants.IS_MUSIC import code.name.monkey.retromusic.Constants.IS_MUSIC
import code.name.monkey.retromusic.extensions.getInt import code.name.monkey.retromusic.extensions.getInt
import code.name.monkey.retromusic.extensions.getLong import code.name.monkey.retromusic.extensions.getLong
@ -83,7 +82,7 @@ object PlaylistSongsLoader {
val artistId = cursor.getLong(AudioColumns.ARTIST_ID) val artistId = cursor.getLong(AudioColumns.ARTIST_ID)
val artistName = cursor.getString(AudioColumns.ARTIST) val artistName = cursor.getString(AudioColumns.ARTIST)
val idInPlaylist = cursor.getLong(Members._ID) val idInPlaylist = cursor.getLong(Members._ID)
val composer = cursor.getString(AudioColumns.COMPOSER) val composer = cursor.getStringOrNull(AudioColumns.COMPOSER)
val albumArtist = cursor.getStringOrNull("album_artist") val albumArtist = cursor.getStringOrNull("album_artist")
return PlaylistSong( return PlaylistSong(
id, id,

View file

@ -16,6 +16,7 @@ package code.name.monkey.retromusic.repository
import android.content.Context import android.content.Context
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.db.* import code.name.monkey.retromusic.db.*
import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.model.*
@ -39,7 +40,7 @@ interface Repository {
fun genresFlow(): Flow<Result<List<Genre>>> fun genresFlow(): Flow<Result<List<Genre>>>
fun historySong(): List<HistoryEntity> fun historySong(): List<HistoryEntity>
fun favorites(): LiveData<List<SongEntity>> fun favorites(): LiveData<List<SongEntity>>
fun observableHistorySongs(): LiveData<List<HistoryEntity>> fun observableHistorySongs(): LiveData<List<Song>>
fun albumById(albumId: Long): Album fun albumById(albumId: Long): Album
fun playlistSongs(playlistEntity: PlaylistEntity): LiveData<List<SongEntity>> fun playlistSongs(playlistEntity: PlaylistEntity): LiveData<List<SongEntity>>
suspend fun fetchAlbums(): List<Album> suspend fun fetchAlbums(): List<Album>
@ -97,6 +98,9 @@ interface Repository {
suspend fun blackListPaths(): List<BlackListStoreEntity> suspend fun blackListPaths(): List<BlackListStoreEntity>
suspend fun deleteSongs(songs: List<Song>) suspend fun deleteSongs(songs: List<Song>)
suspend fun contributor(): List<Contributor> suspend fun contributor(): List<Contributor>
suspend fun searchArtists(query: String): List<Artist>
suspend fun searchSongs(query: String): List<Song>
suspend fun searchAlbums(query: String): List<Album>
} }
class RealRepository( class RealRepository(
@ -115,11 +119,17 @@ class RealRepository(
) : Repository { ) : Repository {
override suspend fun deleteSongs(songs: List<Song>) = roomRepository.deleteSongs(songs) override suspend fun deleteSongs(songs: List<Song>) = roomRepository.deleteSongs(songs)
override suspend fun contributor(): List<Contributor> = localDataRepository.contributors() override suspend fun contributor(): List<Contributor> = localDataRepository.contributors()
override suspend fun searchSongs(query: String): List<Song> = songRepository.songs(query)
override suspend fun searchAlbums(query: String): List<Album> = albumRepository.albums(query)
override suspend fun searchArtists(query: String): List<Artist> =
artistRepository.artists(query)
override suspend fun fetchAlbums(): List<Album> = albumRepository.albums() override suspend fun fetchAlbums(): List<Album> = albumRepository.albums()
override suspend fun albumByIdAsync(albumId: Long): Album = albumRepository.album(albumId) override suspend fun albumByIdAsync(albumId: Long): Album = albumRepository.album(albumId)
@ -311,8 +321,10 @@ class RealRepository(
override suspend fun blackListPaths(): List<BlackListStoreEntity> = override suspend fun blackListPaths(): List<BlackListStoreEntity> =
roomRepository.blackListPaths() roomRepository.blackListPaths()
override fun observableHistorySongs(): LiveData<List<HistoryEntity>> = override fun observableHistorySongs(): LiveData<List<Song>> =
roomRepository.observableHistorySongs() Transformations.map(roomRepository.observableHistorySongs()) {
it.fromHistoryToSongs()
}
override fun historySong(): List<HistoryEntity> = override fun historySong(): List<HistoryEntity> =
roomRepository.historySongs() roomRepository.historySongs()

View file

@ -22,11 +22,11 @@ import java.util.*
class RealSearchRepository( class RealSearchRepository(
private val songRepository: SongRepository, private val songRepository: SongRepository,
private val albumRepository: AlbumRepository, private val albumRepository: AlbumRepository,
private val artistRepository: RealArtistRepository, private val artistRepository: ArtistRepository,
private val roomRepository: RoomRepository,
private val genreRepository: GenreRepository, private val genreRepository: GenreRepository,
private val playlistRepository: PlaylistRepository
) { ) {
fun searchAll(context: Context, query: String?): MutableList<Any> { suspend fun searchAll(context: Context, query: String?): MutableList<Any> {
val results = mutableListOf<Any>() val results = mutableListOf<Any>()
query?.let { searchString -> query?.let { searchString ->
val songs = songRepository.songs(searchString) val songs = songRepository.songs(searchString)
@ -53,8 +53,8 @@ class RealSearchRepository(
results.add(context.resources.getString(R.string.genres)) results.add(context.resources.getString(R.string.genres))
results.addAll(genres) results.addAll(genres)
} }
val playlist = playlistRepository.playlists().filter { playlist -> val playlist = roomRepository.playlistWithSongs().filter { playlist ->
playlist.name.toLowerCase(Locale.getDefault()) playlist.playlistEntity.playlistName.toLowerCase(Locale.getDefault())
.contains(searchString.toLowerCase(Locale.getDefault())) .contains(searchString.toLowerCase(Locale.getDefault()))
} }
if (playlist.isNotEmpty()) { if (playlist.isNotEmpty()) {

View file

@ -11,10 +11,50 @@
~ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ~ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
~ See the GNU General Public License for more details. ~ See the GNU General Public License for more details.
--> -->
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" 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_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSurface"
app:navigationIcon="@drawable/ic_search"
app:popupTheme="?attr/toolbarPopupTheme"
app:title="@null"
tools:ignore="UnusedAttribute">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/appNameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAppearance="@style/TextViewHeadline6"
android:textStyle="bold" />
</androidx.appcompat.widget.Toolbar>
<ViewStub
android:id="@+id/cab_stub"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height" />
</FrameLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/container" android:id="@+id/container"
android:descendantFocusability="beforeDescendants" android:descendantFocusability="beforeDescendants"
android:focusableInTouchMode="true" android:focusableInTouchMode="true"
@ -109,3 +149,4 @@
app:layout_constraintTop_toBottomOf="@+id/imageContainer" /> app:layout_constraintTop_toBottomOf="@+id/imageContainer" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -11,10 +11,50 @@
~ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ~ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
~ See the GNU General Public License for more details. ~ See the GNU General Public License for more details.
--> -->
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" 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_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSurface"
app:navigationIcon="@drawable/ic_search"
app:popupTheme="?attr/toolbarPopupTheme"
app:title="@null"
tools:ignore="UnusedAttribute">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/appNameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAppearance="@style/TextViewHeadline6"
android:textStyle="bold" />
</androidx.appcompat.widget.Toolbar>
<ViewStub
android:id="@+id/cab_stub"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height" />
</FrameLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/container" android:id="@+id/container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -76,3 +116,4 @@
app:layout_constraintTop_toBottomOf="@id/titleWelcome" /> app:layout_constraintTop_toBottomOf="@id/titleWelcome" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:orientation="vertical"
tools:ignore="UnusedAttribute">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/status_bar" />
</FrameLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_keyboard_backspace_black"
app:title="@string/queue"
app:titleTextAppearance="@style/ToolbarTextAppearanceNormal"
tools:ignore="UnusedAttribute" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/nowPlaying"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingHorizontal="78dp"
android:paddingVertical="22dp"
android:text="@string/now_playing"
android:textAppearance="@style/TextViewHeadline6"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingStart="76dp"
android:paddingEnd="8dp"
android:singleLine="true"
android:textAppearance="@style/TextViewSubtitle1"
app:layout_constraintBottom_toTopOf="@id/upNext"
app:layout_constraintEnd_toStartOf="@+id/text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/nowPlaying"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingHorizontal="8dp"
android:singleLine="true"
android:textAppearance="@style/TextViewBody2"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toTopOf="@id/upNext"
app:layout_constraintEnd_toStartOf="@+id/text2"
app:layout_constraintStart_toEndOf="@+id/title"
app:layout_constraintTop_toBottomOf="@id/nowPlaying"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingStart="8dp"
android:paddingEnd="64dp"
android:singleLine="true"
android:textAppearance="@style/TextViewBody2"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toTopOf="@id/upNext"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/text"
app:layout_constraintTop_toBottomOf="@id/nowPlaying"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/upNext"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingHorizontal="78dp"
android:paddingVertical="22dp"
android:text="@string/up_next"
android:textAppearance="@style/TextViewHeadline6"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingBottom="96dp"
android:scrollbars="none"
app:layout_constraintTop_toBottomOf="@id/upNext"
tools:listitem="@layout/item_queue" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.textview.MaterialTextView
android:id="@android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/empty"
android:textAppearance="@style/TextViewNormal"
android:textColor="?colorOnSecondary"
android:visibility="gone"
tools:visibility="visible" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/clearQueue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:text="@string/clear_playing_queue"
android:textAppearance="@style/TextViewHeadline6"
app:icon="@drawable/ic_clear_all" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
android:paddingHorizontal="64dp"
android:background="?rectSelector"
android:clickable="true"
android:focusable="true"
android:minHeight="?attr/listPreferredItemHeight"
android:orientation="horizontal"
tools:ignore="MissingPrefix">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/drag_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|start"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_drag_vertical"
app:tint="?attr/colorControlNormal"
tools:ignore="ContentDescription"
tools:visibility="visible" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/imageTextContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
app:cardCornerRadius="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/drag_view"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:scaleType="centerCrop"
tools:srcCompat="@tools:sample/backgrounds/scenic"
tools:visibility="visible" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/imageText"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:maxLines="1"
android:minHeight="40dp"
android:textAppearance="@style/TextViewSubtitle2"
android:visibility="gone"
tools:text="100"
tools:visibility="visible" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.textview.MaterialTextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingHorizontal="16dp"
android:textAppearance="@style/TextViewSubtitle1"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintBottom_toBottomOf="@id/imageTextContainer"
app:layout_constraintEnd_toStartOf="@id/text"
app:layout_constraintStart_toEndOf="@id/imageTextContainer"
app:layout_constraintTop_toTopOf="@id/imageTextContainer"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingHorizontal="16dp"
android:textAppearance="@style/TextViewBody2"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toBottomOf="@id/title"
app:layout_constraintEnd_toStartOf="@id/text2"
app:layout_constraintStart_toEndOf="@id/title"
app:layout_constraintTop_toTopOf="@id/title"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingHorizontal="16dp"
android:textAppearance="@style/TextViewBody2"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toBottomOf="@id/text"
app:layout_constraintEnd_toStartOf="@id/menu"
app:layout_constraintStart_toEndOf="@id/text"
app:layout_constraintTop_toTopOf="@id/text"
tools:text="@tools:sample/full_names" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/menu"
style="@style/OverFlowButton"
android:layout_gravity="center_vertical"
android:layout_weight="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="?attr/colorControlNormal" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (c) 2019 Hemanth Savarala.
~
~ Licensed under the GNU General Public License v3
~
~ This is free software: you can redistribute it and/or modify it under
~ the terms of the GNU General Public License as published by
~ the Free Software Foundation either version 3 of the License, or (at your option) any later version.
~
~ This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
~ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
~ See the GNU General Public License for more details.
-->
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:background="?attr/rectSelector"
android:minHeight="64dp"
android:padding="14dp"
tools:ignore="UnusedAttribute">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@style/TextViewSubtitle1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@style/TextViewBody2"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/text2"
app:layout_constraintStart_toEndOf="@+id/title"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@style/TextViewBody2"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/text"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?rectSelector"
android:clickable="true"
android:focusable="true">
<FrameLayout
android:id="@+id/dummy_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
android:background="?rectSelector"
android:clickable="true"
android:focusable="true"
android:minHeight="?attr/listPreferredItemHeight"
android:orientation="horizontal"
tools:ignore="MissingPrefix">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/drag_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|start"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_drag_vertical"
app:tint="?attr/colorControlNormal"
tools:ignore="ContentDescription"
tools:visibility="visible" />
<FrameLayout
android:id="@+id/imageContainer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
app:cardCornerRadius="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/drag_view"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/imageText"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:maxLines="1"
android:minWidth="36dp"
android:minHeight="40dp"
android:textAppearance="@style/TextViewSubtitle1"
android:visibility="gone"
tools:text="100"
tools:visibility="visible" />
</FrameLayout>
<com.google.android.material.textview.MaterialTextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingHorizontal="6dp"
android:textAppearance="@style/TextViewSubtitle1"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintBottom_toBottomOf="@id/imageContainer"
app:layout_constraintEnd_toStartOf="@id/text"
app:layout_constraintStart_toEndOf="@id/imageContainer"
app:layout_constraintTop_toTopOf="@id/imageContainer"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingHorizontal="16dp"
android:textAppearance="@style/TextViewBody2"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toBottomOf="@id/title"
app:layout_constraintEnd_toStartOf="@id/text2"
app:layout_constraintStart_toEndOf="@id/title"
app:layout_constraintTop_toTopOf="@id/title"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingHorizontal="16dp"
android:textAppearance="@style/TextViewBody2"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toBottomOf="@id/text"
app:layout_constraintEnd_toStartOf="@id/menu"
app:layout_constraintStart_toEndOf="@id/text"
app:layout_constraintTop_toTopOf="@id/text"
tools:text="@tools:sample/full_names" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/menu"
style="@style/OverFlowButton"
android:layout_gravity="center_vertical"
android:layout_weight="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="?attr/colorControlNormal" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
</FrameLayout>

View file

@ -37,6 +37,67 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/nowPlaying"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="12dp"
android:text="@string/now_playing"
android:textAppearance="@style/TextViewHeadline6"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:paddingStart="72dp"
android:paddingEnd="16dp"
android:textAppearance="@style/TextViewSubtitle1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/nowPlaying"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:paddingStart="72dp"
android:paddingEnd="16dp"
android:textAppearance="@style/TextViewBody2"
android:textColor="?android:textColorSecondary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/upNext"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="12dp"
android:text="@string/up_next"
android:textAppearance="@style/TextViewHeadline6"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text" />
<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"
@ -45,7 +106,10 @@
android:overScrollMode="never" android:overScrollMode="never"
android:paddingBottom="96dp" android:paddingBottom="96dp"
android:scrollbars="none" android:scrollbars="none"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" /> app:layout_constraintTop_toBottomOf="@id/upNext" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@android:id/empty" android:id="@android:id/empty"
@ -68,6 +132,5 @@
android:textAppearance="@style/TextViewHeadline6" android:textAppearance="@style/TextViewHeadline6"
app:icon="@drawable/ic_clear_all" /> app:icon="@drawable/ic_clear_all" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout> </LinearLayout>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" 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"
@ -20,24 +20,25 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center_vertical|start" android:layout_gravity="center_vertical|start"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_drag_vertical" app:srcCompat="@drawable/ic_drag_vertical"
app:tint="?attr/colorControlNormal" app:tint="?attr/colorControlNormal"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription"
tools:visibility="visible" />
<FrameLayout
android:id="@+id/imageContainer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="0"
android:paddingStart="16dp"
android:paddingEnd="0dp">
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:id="@+id/imageTextContainer" android:id="@+id/imageTextContainer"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
app:cardCornerRadius="6dp"> android:layout_marginStart="16dp"
app:cardCornerRadius="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/drag_view"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image" android:id="@+id/image"
@ -46,7 +47,8 @@
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:gravity="center_vertical" android:gravity="center_vertical"
android:scaleType="centerCrop" android:scaleType="centerCrop"
tools:srcCompat="@tools:sample/backgrounds/scenic" /> tools:srcCompat="@tools:sample/backgrounds/scenic"
tools:visibility="visible" />
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/imageText" android:id="@+id/imageText"
@ -60,45 +62,49 @@
tools:text="100" tools:text="100"
tools:visibility="visible" /> tools:visibility="visible" />
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
</FrameLayout>
<LinearLayout
android:id="@+id/title_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1.0"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/title" android:id="@+id/title"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:paddingHorizontal="16dp"
android:textAppearance="@style/TextViewSubtitle1" android:textAppearance="@style/TextViewSubtitle1"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
app:layout_constraintBottom_toTopOf="@+id/text"
app:layout_constraintEnd_toStartOf="@id/menu"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@id/imageTextContainer"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="@tools:sample/full_names" /> tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/text" android:id="@+id/text"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:paddingHorizontal="16dp"
android:textAppearance="@style/TextViewBody2" android:textAppearance="@style/TextViewBody2"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/menu"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@id/imageTextContainer"
app:layout_constraintTop_toBottomOf="@+id/title"
tools:text="@tools:sample/full_names" /> tools:text="@tools:sample/full_names" />
</LinearLayout>
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/menu" android:id="@+id/menu"
style="@style/OverFlowButton" style="@style/OverFlowButton"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_weight="0" android:layout_weight="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="?attr/colorControlNormal" /> app:tint="?attr/colorControlNormal" />
</LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -32,7 +32,7 @@
app:layout_constraintEnd_toEndOf="parent" 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"
tools:text="@tools:sample/first_names" /> tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/text" android:id="@+id/text"
@ -44,7 +44,6 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title" app:layout_constraintTop_toBottomOf="@id/title"
tools:text="@tools:sample/first_names" /> tools:text="@tools:sample/full_names" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -13,11 +13,16 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<LinearLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical" android:layout_marginStart="1dp"
android:minHeight="64dp" android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
android:background="?rectSelector"
android:clickable="true"
android:focusable="true"
android:minHeight="?attr/listPreferredItemHeight"
android:orientation="horizontal" android:orientation="horizontal"
tools:ignore="MissingPrefix"> tools:ignore="MissingPrefix">
@ -26,71 +31,86 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center_vertical|start" android:layout_gravity="center_vertical|start"
android:padding="8dp"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_drag_vertical" app:srcCompat="@drawable/ic_drag_vertical"
app:tint="?attr/colorControlNormal" app:tint="?attr/colorControlNormal"
tools:ignore="ContentDescription" tools:ignore="ContentDescription"
tools:visibility="visible" /> tools:visibility="visible" />
<FrameLayout <FrameLayout
android:id="@+id/imageContainer" android:id="@+id/imageContainer"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_weight="0"> android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
app:cardCornerRadius="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/drag_view"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/imageText" android:id="@+id/imageText"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center" android:gravity="center"
android:maxLines="1" android:maxLines="1"
android:minWidth="36dp" android:minWidth="36dp"
android:minHeight="40dp" android:minHeight="40dp"
android:textAppearance="@style/TextViewSubtitle1" android:textAppearance="@style/TextViewSubtitle1"
android:visibility="gone" android:visibility="gone"
tools:text="1" tools:text="100"
tools:visibility="visible" /> tools:visibility="visible" />
</FrameLayout> </FrameLayout>
<LinearLayout
android:id="@+id/title_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1.0"
android:orientation="vertical">
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/title" android:id="@+id/title"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:paddingHorizontal="16dp"
android:textAppearance="@style/TextViewSubtitle1" android:textAppearance="@style/TextViewSubtitle1"
android:textSize="16sp" android:textColor="?android:attr/textColorPrimary"
tools:text="Song name" /> app:layout_constraintBottom_toTopOf="@+id/text"
app:layout_constraintEnd_toStartOf="@id/menu"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@id/imageContainer"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="@tools:sample/full_names" />
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/text" android:id="@+id/text"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
tools:text="Song details" /> android:paddingHorizontal="16dp"
</LinearLayout> android:textAppearance="@style/TextViewBody2"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/menu"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@id/imageContainer"
app:layout_constraintTop_toBottomOf="@+id/title"
tools:text="@tools:sample/full_names" />
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/menu" android:id="@+id/menu"
style="@style/OverFlowButton" style="@style/OverFlowButton"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_weight="0" android:layout_weight="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="?attr/colorControlNormal" /> app:tint="?attr/colorControlNormal" />
</LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout> </FrameLayout>
</FrameLayout> </FrameLayout>

View file

@ -6,7 +6,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start" android:layout_gravity="start"
android:gravity="start" android:gravity="start"
android:paddingHorizontal="16dp" android:layout_marginStart="@dimen/toolbar_margin_horizontal"
android:layout_marginEnd="@dimen/toolbar_margin_horizontal"
android:paddingVertical="12dp" android:paddingVertical="12dp"
android:textAppearance="@style/TextViewOverline" android:textAppearance="@style/TextViewOverline"
android:textStyle="bold" android:textStyle="bold"

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -370,7 +370,7 @@
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>
<string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string> <string name="rate_on_google_play_summary">Love this app? Let us know in the Google Play Store how we can make it even better</string>
<string name="recent_albums">Recent albums</string> <string name="recent_albums">Recent albums</string>

View file

@ -604,7 +604,7 @@
<string name="purchase_summary">*Think before buying, don\'t ask for refund.</string> <string name="purchase_summary">*Think before buying, don\'t ask for refund.</string>
<string name="queue">Queue</string> <string name="queue">Playing Queue</string>
<string name="rate_app">Rate the app</string> <string name="rate_app">Rate the app</string>