Add ability to play from user queue
Add the ability to play from the user queue, also append some extra song actions.
This commit is contained in:
parent
2be7d34601
commit
4fb4120342
14 changed files with 160 additions and 136 deletions
|
|
@ -7,7 +7,7 @@ import android.view.View
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import org.oxycblt.auxio.playback.PlaybackService
|
import org.oxycblt.auxio.playback.PlaybackService
|
||||||
import org.oxycblt.auxio.theme.accent
|
import org.oxycblt.auxio.ui.accent
|
||||||
|
|
||||||
// FIXME: Fix bug where fast navigation will break the animations and
|
// FIXME: Fix bug where fast navigation will break the animations and
|
||||||
// lead to nothing being displayed [Possibly Un-fixable]
|
// lead to nothing being displayed [Possibly Un-fixable]
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ import org.oxycblt.auxio.library.LibraryFragment
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.songs.SongsFragment
|
import org.oxycblt.auxio.songs.SongsFragment
|
||||||
import org.oxycblt.auxio.theme.accent
|
import org.oxycblt.auxio.ui.accent
|
||||||
import org.oxycblt.auxio.theme.getInactiveAlpha
|
import org.oxycblt.auxio.ui.getInactiveAlpha
|
||||||
import org.oxycblt.auxio.theme.getTransparentAccent
|
import org.oxycblt.auxio.ui.getTransparentAccent
|
||||||
import org.oxycblt.auxio.theme.toColor
|
import org.oxycblt.auxio.ui.toColor
|
||||||
|
|
||||||
class MainFragment : Fragment() {
|
class MainFragment : Fragment() {
|
||||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ import org.oxycblt.auxio.detail.adapters.DetailSongAdapter
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||||
import org.oxycblt.auxio.theme.applyDivider
|
import org.oxycblt.auxio.ui.applyDivider
|
||||||
import org.oxycblt.auxio.theme.disable
|
import org.oxycblt.auxio.ui.disable
|
||||||
|
|
||||||
class AlbumDetailFragment : Fragment() {
|
class AlbumDetailFragment : Fragment() {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ import org.oxycblt.auxio.databinding.FragmentArtistDetailBinding
|
||||||
import org.oxycblt.auxio.detail.adapters.DetailAlbumAdapter
|
import org.oxycblt.auxio.detail.adapters.DetailAlbumAdapter
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.theme.applyDivider
|
import org.oxycblt.auxio.ui.applyDivider
|
||||||
import org.oxycblt.auxio.theme.disable
|
import org.oxycblt.auxio.ui.disable
|
||||||
|
|
||||||
class ArtistDetailFragment : Fragment() {
|
class ArtistDetailFragment : Fragment() {
|
||||||
private val args: ArtistDetailFragmentArgs by navArgs()
|
private val args: ArtistDetailFragmentArgs by navArgs()
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ import org.oxycblt.auxio.databinding.FragmentGenreDetailBinding
|
||||||
import org.oxycblt.auxio.detail.adapters.DetailArtistAdapter
|
import org.oxycblt.auxio.detail.adapters.DetailArtistAdapter
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.theme.applyDivider
|
import org.oxycblt.auxio.ui.applyDivider
|
||||||
import org.oxycblt.auxio.theme.disable
|
import org.oxycblt.auxio.ui.disable
|
||||||
|
|
||||||
class GenreDetailFragment : Fragment() {
|
class GenreDetailFragment : Fragment() {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,10 @@ import org.oxycblt.auxio.music.MusicStore
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||||
import org.oxycblt.auxio.theme.applyColor
|
import org.oxycblt.auxio.ui.applyColor
|
||||||
import org.oxycblt.auxio.theme.applyDivider
|
import org.oxycblt.auxio.ui.applyDivider
|
||||||
import org.oxycblt.auxio.theme.resolveAttr
|
import org.oxycblt.auxio.ui.resolveAttr
|
||||||
|
import org.oxycblt.auxio.ui.showActionMenuForSong
|
||||||
|
|
||||||
// A Fragment to show all the music in the Library.
|
// A Fragment to show all the music in the Library.
|
||||||
class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
||||||
|
|
@ -54,7 +55,11 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
||||||
{
|
{
|
||||||
navToItem(it)
|
navToItem(it)
|
||||||
},
|
},
|
||||||
{ data, view -> }
|
{ data, view ->
|
||||||
|
if (data is Song) {
|
||||||
|
showActionMenuForSong(requireContext(), data, view, playbackModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// --- UI SETUP ---
|
// --- UI SETUP ---
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,8 @@ import androidx.navigation.fragment.findNavController
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentPlaybackBinding
|
import org.oxycblt.auxio.databinding.FragmentPlaybackBinding
|
||||||
import org.oxycblt.auxio.playback.state.LoopMode
|
import org.oxycblt.auxio.playback.state.LoopMode
|
||||||
import org.oxycblt.auxio.theme.accent
|
import org.oxycblt.auxio.ui.accent
|
||||||
import org.oxycblt.auxio.theme.disable
|
import org.oxycblt.auxio.ui.toColor
|
||||||
import org.oxycblt.auxio.theme.enable
|
|
||||||
import org.oxycblt.auxio.theme.toColor
|
|
||||||
|
|
||||||
// TODO: Add a swipe-to-next-track function using a ViewPager
|
// TODO: Add a swipe-to-next-track function using a ViewPager
|
||||||
class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
|
|
@ -99,20 +97,6 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
playbackModel.index.observe(viewLifecycleOwner) {
|
|
||||||
if (it > 0) {
|
|
||||||
binding.playbackSkipPrev.enable(requireContext())
|
|
||||||
} else {
|
|
||||||
binding.playbackSkipPrev.disable(requireContext())
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it < playbackModel.queue.value!!.lastIndex) {
|
|
||||||
binding.playbackSkipNext.enable(requireContext())
|
|
||||||
} else {
|
|
||||||
binding.playbackSkipNext.disable(requireContext())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playbackModel.isPlaying.observe(viewLifecycleOwner) {
|
playbackModel.isPlaying.observe(viewLifecycleOwner) {
|
||||||
if (it) {
|
if (it) {
|
||||||
// Animate the playing status and switch the button to the accent color
|
// Animate the playing status and switch the button to the accent color
|
||||||
|
|
@ -186,14 +170,6 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
queueMenuItem.isEnabled = true
|
queueMenuItem.isEnabled = true
|
||||||
queueMenuItem.icon = iconQueueActive
|
queueMenuItem.icon = iconQueueActive
|
||||||
}
|
}
|
||||||
|
|
||||||
// If someone edits the queue to make it have no songs left, then disable the
|
|
||||||
// skip next button.
|
|
||||||
if (playbackModel.index.value!! == it.size) {
|
|
||||||
binding.playbackSkipNext.disable(requireContext())
|
|
||||||
} else {
|
|
||||||
binding.playbackSkipNext.enable(requireContext())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
playbackModel.userQueue.observe(viewLifecycleOwner) {
|
playbackModel.userQueue.observe(viewLifecycleOwner) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentQueueListBinding
|
import org.oxycblt.auxio.databinding.FragmentQueueListBinding
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||||
import org.oxycblt.auxio.theme.applyDivider
|
import org.oxycblt.auxio.ui.applyDivider
|
||||||
|
|
||||||
class QueueListFragment(private val type: Int) : Fragment() {
|
class QueueListFragment(private val type: Int) : Fragment() {
|
||||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||||
|
|
@ -53,14 +53,12 @@ class QueueListFragment(private val type: Int) : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
playbackModel.mode.observe(viewLifecycleOwner) {
|
playbackModel.mode.observe(viewLifecycleOwner) {
|
||||||
if (it == PlaybackMode.ALL_SONGS) {
|
|
||||||
binding.queueHeader.setText(R.string.label_next_songs)
|
|
||||||
} else {
|
|
||||||
binding.queueHeader.text = getString(
|
binding.queueHeader.text = getString(
|
||||||
R.string.format_next_from, playbackModel.parent.value!!.name
|
R.string.format_next_from,
|
||||||
|
if (it == PlaybackMode.ALL_SONGS) getString(R.string.title_all_songs)
|
||||||
|
else playbackModel.parent.value!!.name
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
playbackModel.nextItemsInQueue.observe(viewLifecycleOwner) {
|
playbackModel.nextItemsInQueue.observe(viewLifecycleOwner) {
|
||||||
if (it.isEmpty()) {
|
if (it.isEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,12 @@ class PlaybackStateManager private constructor() {
|
||||||
fun next() {
|
fun next() {
|
||||||
resetLoopMode()
|
resetLoopMode()
|
||||||
|
|
||||||
|
if (mUserQueue.isNotEmpty()) {
|
||||||
|
updatePlayback(mUserQueue[0])
|
||||||
|
mUserQueue.removeAt(0)
|
||||||
|
|
||||||
|
forceUserQueueUpdate()
|
||||||
|
} else {
|
||||||
if (mIndex < mQueue.lastIndex) {
|
if (mIndex < mQueue.lastIndex) {
|
||||||
mIndex = mIndex.inc()
|
mIndex = mIndex.inc()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -230,6 +236,7 @@ class PlaybackStateManager private constructor() {
|
||||||
|
|
||||||
forceQueueUpdate()
|
forceQueueUpdate()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun prev() {
|
fun prev() {
|
||||||
if (mIndex > 0) {
|
if (mIndex > 0) {
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,15 @@ import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.PopupMenu
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentSongsBinding
|
import org.oxycblt.auxio.databinding.FragmentSongsBinding
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
import org.oxycblt.auxio.music.Song
|
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||||
import org.oxycblt.auxio.theme.applyDivider
|
import org.oxycblt.auxio.ui.applyDivider
|
||||||
|
import org.oxycblt.auxio.ui.showActionMenuForSong
|
||||||
|
|
||||||
class SongsFragment : Fragment() {
|
class SongsFragment : Fragment() {
|
||||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||||
|
|
@ -47,7 +46,7 @@ class SongsFragment : Fragment() {
|
||||||
playbackModel.playSong(it, PlaybackMode.ALL_SONGS)
|
playbackModel.playSong(it, PlaybackMode.ALL_SONGS)
|
||||||
},
|
},
|
||||||
{ data, view ->
|
{ data, view ->
|
||||||
showActionMenuForSong(data, view)
|
showActionMenuForSong(requireContext(), data, view, playbackModel)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
applyDivider()
|
applyDivider()
|
||||||
|
|
@ -58,21 +57,4 @@ class SongsFragment : Fragment() {
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showActionMenuForSong(song: Song, view: View) {
|
|
||||||
// TODO: Replace this with something nicer
|
|
||||||
PopupMenu(requireContext(), view).apply {
|
|
||||||
inflate(R.menu.menu_song_actions)
|
|
||||||
setOnMenuItemClickListener {
|
|
||||||
if (it.itemId == R.id.action_queue_add) {
|
|
||||||
playbackModel.addToUserQueue(song)
|
|
||||||
|
|
||||||
return@setOnMenuItemClickListener true
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
98
app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt
Normal file
98
app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
package org.oxycblt.auxio.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.ColorStateList
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.text.SpannableString
|
||||||
|
import android.text.style.ForegroundColorSpan
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.ImageButton
|
||||||
|
import android.widget.PopupMenu
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.ColorInt
|
||||||
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import org.oxycblt.auxio.R
|
||||||
|
import org.oxycblt.auxio.music.Song
|
||||||
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
|
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||||
|
|
||||||
|
// Functions for managing UI elements [Not Colors]
|
||||||
|
|
||||||
|
fun showActionMenuForSong(
|
||||||
|
context: Context,
|
||||||
|
song: Song,
|
||||||
|
view: View,
|
||||||
|
playbackModel: PlaybackViewModel
|
||||||
|
) {
|
||||||
|
// TODO: Replace this with a BottomSheet dialog?
|
||||||
|
PopupMenu(context, view).apply {
|
||||||
|
inflate(R.menu.menu_song_actions)
|
||||||
|
setOnMenuItemClickListener {
|
||||||
|
return@setOnMenuItemClickListener when (it.itemId) {
|
||||||
|
R.id.action_queue_add -> {
|
||||||
|
playbackModel.addToUserQueue(song)
|
||||||
|
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
context.getString(R.string.label_queue_added),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.action_play_artist -> {
|
||||||
|
playbackModel.playSong(song, PlaybackMode.IN_ARTIST)
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.action_play_album -> {
|
||||||
|
playbackModel.playSong(song, PlaybackMode.IN_ALBUM)
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply a color to a Menu Item
|
||||||
|
fun MenuItem.applyColor(@ColorInt color: Int) {
|
||||||
|
SpannableString(title).apply {
|
||||||
|
setSpan(ForegroundColorSpan(color), 0, length, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
title = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable an ImageButton
|
||||||
|
fun ImageButton.disable(context: Context) {
|
||||||
|
if (isEnabled) {
|
||||||
|
imageTintList = ColorStateList.valueOf(
|
||||||
|
R.color.inactive_color.toColor(context)
|
||||||
|
)
|
||||||
|
|
||||||
|
isEnabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply a custom vertical divider
|
||||||
|
fun RecyclerView.applyDivider() {
|
||||||
|
val div = DividerItemDecoration(
|
||||||
|
context,
|
||||||
|
DividerItemDecoration.VERTICAL
|
||||||
|
)
|
||||||
|
|
||||||
|
div.setDrawable(
|
||||||
|
ColorDrawable(
|
||||||
|
R.color.divider_color.toColor(context)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
addItemDecoration(div)
|
||||||
|
}
|
||||||
|
|
@ -1,22 +1,16 @@
|
||||||
package org.oxycblt.auxio.theme
|
package org.oxycblt.auxio.ui
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.drawable.ColorDrawable
|
|
||||||
import android.text.SpannableString
|
|
||||||
import android.text.style.ForegroundColorSpan
|
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.MenuItem
|
|
||||||
import android.widget.ImageButton
|
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.annotation.ColorRes
|
import androidx.annotation.ColorRes
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.ColorUtils
|
import androidx.core.graphics.ColorUtils
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
|
|
||||||
|
// Functions for managing colors/accents/whatever.
|
||||||
|
|
||||||
// Pairs of the base accent and its theme
|
// Pairs of the base accent and its theme
|
||||||
private val ACCENTS = listOf(
|
private val ACCENTS = listOf(
|
||||||
Pair(R.color.red, R.style.Theme_Red), // 0
|
Pair(R.color.red, R.style.Theme_Red), // 0
|
||||||
|
|
@ -85,49 +79,3 @@ fun resolveAttr(context: Context, @AttrRes attr: Int): Int {
|
||||||
|
|
||||||
return color.toColor(context)
|
return color.toColor(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply a color to a Menu Item
|
|
||||||
fun MenuItem.applyColor(@ColorInt color: Int) {
|
|
||||||
SpannableString(title).apply {
|
|
||||||
setSpan(ForegroundColorSpan(color), 0, length, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
title = this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable an ImageButton
|
|
||||||
fun ImageButton.disable(context: Context) {
|
|
||||||
if (isEnabled) {
|
|
||||||
imageTintList = ColorStateList.valueOf(
|
|
||||||
R.color.inactive_color.toColor(context)
|
|
||||||
)
|
|
||||||
|
|
||||||
isEnabled = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable an ImageButton
|
|
||||||
fun ImageButton.enable(context: Context) {
|
|
||||||
if (!isEnabled) {
|
|
||||||
imageTintList = ColorStateList.valueOf(
|
|
||||||
R.color.control_color.toColor(context)
|
|
||||||
)
|
|
||||||
|
|
||||||
isEnabled = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply a custom vertical divider
|
|
||||||
fun RecyclerView.applyDivider() {
|
|
||||||
val div = DividerItemDecoration(
|
|
||||||
context,
|
|
||||||
DividerItemDecoration.VERTICAL
|
|
||||||
)
|
|
||||||
|
|
||||||
div.setDrawable(
|
|
||||||
ColorDrawable(
|
|
||||||
R.color.divider_color.toColor(context)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
addItemDecoration(div)
|
|
||||||
}
|
|
||||||
|
|
@ -4,4 +4,12 @@
|
||||||
android:id="@+id/action_queue_add"
|
android:id="@+id/action_queue_add"
|
||||||
android:title="@string/label_queue_add"
|
android:title="@string/label_queue_add"
|
||||||
android:icon="@drawable/ic_user_queue" />
|
android:icon="@drawable/ic_user_queue" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_play_artist"
|
||||||
|
android:title="@string/label_play_artist"
|
||||||
|
android:icon="@drawable/ic_artist" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_play_album"
|
||||||
|
android:title="@string/label_play_album"
|
||||||
|
android:icon="@drawable/ic_album" />
|
||||||
</menu>
|
</menu>
|
||||||
|
|
@ -25,10 +25,12 @@
|
||||||
<string name="label_sort_alpha_up">Z-A</string>
|
<string name="label_sort_alpha_up">Z-A</string>
|
||||||
<string name="label_shuffle">Shuffle</string>
|
<string name="label_shuffle">Shuffle</string>
|
||||||
<string name="label_play">Play</string>
|
<string name="label_play">Play</string>
|
||||||
|
<string name="label_play_artist">Play from artist</string>
|
||||||
|
<string name="label_play_album">Play from album</string>
|
||||||
<string name="label_queue">Queue</string>
|
<string name="label_queue">Queue</string>
|
||||||
<string name="label_queue_add">Add to queue</string>
|
<string name="label_queue_add">Add to queue</string>
|
||||||
|
<string name="label_queue_added">Added to queue</string>
|
||||||
<string name="label_next_user_queue">Next in Queue</string>
|
<string name="label_next_user_queue">Next in Queue</string>
|
||||||
<string name="label_next_songs">Next from: All Songs</string>
|
|
||||||
<string name="label_empty_queue">Nothing here.</string>
|
<string name="label_empty_queue">Nothing here.</string>
|
||||||
<string name="label_notification_playback">Music Playback</string>
|
<string name="label_notification_playback">Music Playback</string>
|
||||||
<string name="label_service_playback">The music playback service for Auxio.</string>
|
<string name="label_service_playback">The music playback service for Auxio.</string>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue