diff --git a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt
index 70a931bd5..4ba9c0091 100644
--- a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt
+++ b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt
@@ -7,7 +7,7 @@ import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
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
// lead to nothing being displayed [Possibly Un-fixable]
diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt
index 62bc38314..5aaecde3a 100644
--- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt
@@ -17,10 +17,10 @@ import org.oxycblt.auxio.library.LibraryFragment
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.songs.SongsFragment
-import org.oxycblt.auxio.theme.accent
-import org.oxycblt.auxio.theme.getInactiveAlpha
-import org.oxycblt.auxio.theme.getTransparentAccent
-import org.oxycblt.auxio.theme.toColor
+import org.oxycblt.auxio.ui.accent
+import org.oxycblt.auxio.ui.getInactiveAlpha
+import org.oxycblt.auxio.ui.getTransparentAccent
+import org.oxycblt.auxio.ui.toColor
class MainFragment : Fragment() {
private val playbackModel: PlaybackViewModel by activityViewModels()
diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt
index a6b433793..13df0c5e6 100644
--- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt
@@ -15,8 +15,8 @@ import org.oxycblt.auxio.detail.adapters.DetailSongAdapter
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.playback.state.PlaybackMode
-import org.oxycblt.auxio.theme.applyDivider
-import org.oxycblt.auxio.theme.disable
+import org.oxycblt.auxio.ui.applyDivider
+import org.oxycblt.auxio.ui.disable
class AlbumDetailFragment : Fragment() {
diff --git a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt
index b9f9473eb..4739d5846 100644
--- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt
@@ -14,8 +14,8 @@ import org.oxycblt.auxio.databinding.FragmentArtistDetailBinding
import org.oxycblt.auxio.detail.adapters.DetailAlbumAdapter
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel
-import org.oxycblt.auxio.theme.applyDivider
-import org.oxycblt.auxio.theme.disable
+import org.oxycblt.auxio.ui.applyDivider
+import org.oxycblt.auxio.ui.disable
class ArtistDetailFragment : Fragment() {
private val args: ArtistDetailFragmentArgs by navArgs()
diff --git a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt
index b2d0539f4..501bde764 100644
--- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt
@@ -14,8 +14,8 @@ import org.oxycblt.auxio.databinding.FragmentGenreDetailBinding
import org.oxycblt.auxio.detail.adapters.DetailArtistAdapter
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel
-import org.oxycblt.auxio.theme.applyDivider
-import org.oxycblt.auxio.theme.disable
+import org.oxycblt.auxio.ui.applyDivider
+import org.oxycblt.auxio.ui.disable
class GenreDetailFragment : Fragment() {
diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt
index e6b3f4188..f39438efc 100644
--- a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt
@@ -27,9 +27,10 @@ import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.playback.state.PlaybackMode
-import org.oxycblt.auxio.theme.applyColor
-import org.oxycblt.auxio.theme.applyDivider
-import org.oxycblt.auxio.theme.resolveAttr
+import org.oxycblt.auxio.ui.applyColor
+import org.oxycblt.auxio.ui.applyDivider
+import org.oxycblt.auxio.ui.resolveAttr
+import org.oxycblt.auxio.ui.showActionMenuForSong
// A Fragment to show all the music in the Library.
class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
@@ -54,7 +55,11 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
{
navToItem(it)
},
- { data, view -> }
+ { data, view ->
+ if (data is Song) {
+ showActionMenuForSong(requireContext(), data, view, playbackModel)
+ }
+ }
)
// --- UI SETUP ---
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt
index 05d0250a6..babb2ef93 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt
@@ -16,10 +16,8 @@ import androidx.navigation.fragment.findNavController
import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentPlaybackBinding
import org.oxycblt.auxio.playback.state.LoopMode
-import org.oxycblt.auxio.theme.accent
-import org.oxycblt.auxio.theme.disable
-import org.oxycblt.auxio.theme.enable
-import org.oxycblt.auxio.theme.toColor
+import org.oxycblt.auxio.ui.accent
+import org.oxycblt.auxio.ui.toColor
// TODO: Add a swipe-to-next-track function using a ViewPager
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) {
if (it) {
// 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.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) {
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueListFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueListFragment.kt
index 36a7adb71..3d05b0cd7 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueListFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueListFragment.kt
@@ -14,7 +14,7 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentQueueListBinding
import org.oxycblt.auxio.playback.PlaybackViewModel
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() {
private val playbackModel: PlaybackViewModel by activityViewModels()
@@ -53,13 +53,11 @@ class QueueListFragment(private val type: Int) : Fragment() {
}
playbackModel.mode.observe(viewLifecycleOwner) {
- if (it == PlaybackMode.ALL_SONGS) {
- binding.queueHeader.setText(R.string.label_next_songs)
- } else {
- binding.queueHeader.text = getString(
- R.string.format_next_from, playbackModel.parent.value!!.name
- )
- }
+ binding.queueHeader.text = getString(
+ 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) {
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt
index ab05e3389..c08e44d11 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt
@@ -216,19 +216,26 @@ class PlaybackStateManager private constructor() {
fun next() {
resetLoopMode()
- if (mIndex < mQueue.lastIndex) {
- mIndex = mIndex.inc()
+ if (mUserQueue.isNotEmpty()) {
+ updatePlayback(mUserQueue[0])
+ mUserQueue.removeAt(0)
+
+ forceUserQueueUpdate()
} else {
- // TODO: Implement option to make the playlist loop instead of stop
- mQueue = mutableListOf()
- mSong = null
+ if (mIndex < mQueue.lastIndex) {
+ mIndex = mIndex.inc()
+ } else {
+ // TODO: Implement option to make the playlist loop instead of stop
+ mQueue = mutableListOf()
+ mSong = null
- return
+ return
+ }
+
+ updatePlayback(mQueue[mIndex])
+
+ forceQueueUpdate()
}
-
- updatePlayback(mQueue[mIndex])
-
- forceQueueUpdate()
}
fun prev() {
diff --git a/app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt b/app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt
index ec574788b..2d034b0fa 100644
--- a/app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt
@@ -5,16 +5,15 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.PopupMenu
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentSongsBinding
import org.oxycblt.auxio.music.MusicStore
-import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackViewModel
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() {
private val playbackModel: PlaybackViewModel by activityViewModels()
@@ -47,7 +46,7 @@ class SongsFragment : Fragment() {
playbackModel.playSong(it, PlaybackMode.ALL_SONGS)
},
{ data, view ->
- showActionMenuForSong(data, view)
+ showActionMenuForSong(requireContext(), data, view, playbackModel)
}
)
applyDivider()
@@ -58,21 +57,4 @@ class SongsFragment : Fragment() {
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()
- }
- }
}
diff --git a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt
new file mode 100644
index 000000000..cdd85e4ad
--- /dev/null
+++ b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt
@@ -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)
+}
diff --git a/app/src/main/java/org/oxycblt/auxio/theme/ThemeUtils.kt b/app/src/main/java/org/oxycblt/auxio/ui/ThemeUtils.kt
similarity index 64%
rename from app/src/main/java/org/oxycblt/auxio/theme/ThemeUtils.kt
rename to app/src/main/java/org/oxycblt/auxio/ui/ThemeUtils.kt
index 75166634f..2a9095709 100644
--- a/app/src/main/java/org/oxycblt/auxio/theme/ThemeUtils.kt
+++ b/app/src/main/java/org/oxycblt/auxio/ui/ThemeUtils.kt
@@ -1,22 +1,16 @@
-package org.oxycblt.auxio.theme
+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.util.TypedValue
-import android.view.MenuItem
-import android.widget.ImageButton
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils
-import androidx.recyclerview.widget.DividerItemDecoration
-import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.R
+// Functions for managing colors/accents/whatever.
+
// Pairs of the base accent and its theme
private val ACCENTS = listOf(
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)
}
-
-// 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)
-}
diff --git a/app/src/main/res/menu/menu_song_actions.xml b/app/src/main/res/menu/menu_song_actions.xml
index 125309274..018077ecd 100644
--- a/app/src/main/res/menu/menu_song_actions.xml
+++ b/app/src/main/res/menu/menu_song_actions.xml
@@ -4,4 +4,12 @@
android:id="@+id/action_queue_add"
android:title="@string/label_queue_add"
android:icon="@drawable/ic_user_queue" />
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index ed599206e..7a56ef79c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -25,10 +25,12 @@
Z-A
Shuffle
Play
+ Play from artist
+ Play from album
Queue
Add to queue
+ Added to queue
Next in Queue
- Next from: All Songs
Nothing here.
Music Playback
The music playback service for Auxio.