Add song playback mode option
Add an option to customize whether a song should play from its artist, its album, or all songs when selected.
This commit is contained in:
parent
859391e69b
commit
aaa1ad1a3d
14 changed files with 137 additions and 50 deletions
|
@ -25,7 +25,7 @@ import org.oxycblt.auxio.music.BaseModel
|
|||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.ui.applyColor
|
||||
import org.oxycblt.auxio.ui.resolveAttr
|
||||
import org.oxycblt.auxio.ui.setupAlbumActions
|
||||
|
@ -197,7 +197,9 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
|||
// If the item is a song [That was selected through search], then update the playback
|
||||
// to that song instead of doing any navigation
|
||||
if (baseModel is Song) {
|
||||
playbackModel.playSong(baseModel, PlaybackMode.ALL_SONGS)
|
||||
val settingsManager = SettingsManager.getInstance()
|
||||
|
||||
playbackModel.playSong(baseModel, settingsManager.songPlaybackMode)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -1,23 +1,16 @@
|
|||
package org.oxycblt.auxio.library.adapters
|
||||
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.AsyncListDiffer
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Header
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.recycler.viewholders.AlbumViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.ArtistViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.GenreViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.HeaderViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.SongViewHolder
|
||||
|
||||
/**
|
||||
* A near-identical adapter as [SearchAdapter] but this one isn't a [ListAdapter]
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package org.oxycblt.auxio.library.adapters
|
||||
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.AsyncListDiffer
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.music.Album
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@file:Suppress("unused")
|
||||
|
||||
package org.oxycblt.auxio.playback
|
||||
|
||||
import android.content.Context
|
||||
|
@ -45,7 +43,7 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
|
|||
val userQueue: LiveData<MutableList<Song>> get() = mUserQueue
|
||||
|
||||
private val mIndex = MutableLiveData(0)
|
||||
val index: LiveData<Int> get() = mIndex
|
||||
// val index: LiveData<Int> get() = mIndex
|
||||
|
||||
private val mMode = MutableLiveData(PlaybackMode.ALL_SONGS)
|
||||
val mode: LiveData<PlaybackMode> get() = mMode
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.oxycblt.auxio.playback.state
|
||||
|
||||
import java.lang.IllegalArgumentException
|
||||
|
||||
// Enum for instruction how the queue should function.
|
||||
// ALL SONGS -> Play from all songs
|
||||
// IN_ARTIST -> Play from the songs of the artist
|
||||
|
@ -32,5 +34,17 @@ enum class PlaybackMode {
|
|||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun valueOfOrFallback(value: String?): PlaybackMode {
|
||||
if (value == null) {
|
||||
return ALL_SONGS
|
||||
}
|
||||
|
||||
return try {
|
||||
valueOf(value)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
ALL_SONGS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@file:Suppress("unused")
|
||||
|
||||
package org.oxycblt.auxio.settings
|
||||
|
||||
import android.os.Bundle
|
||||
|
@ -21,6 +19,7 @@ import org.oxycblt.auxio.ui.ACCENTS
|
|||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.getDetailedAccentSummary
|
||||
|
||||
@Suppress("UNUSED")
|
||||
class SettingsListFragment : PreferenceFragmentCompat() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.oxycblt.auxio.settings
|
|||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.recycler.DisplayMode
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
import org.oxycblt.auxio.ui.ACCENTS
|
||||
|
@ -51,14 +52,12 @@ class SettingsManager private constructor(context: Context) :
|
|||
get() = sharedPrefs.getBoolean(Keys.KEY_USE_ALT_NOTIFICATION_ACTION, false)
|
||||
|
||||
val libraryDisplayMode: DisplayMode
|
||||
get() {
|
||||
return DisplayMode.valueOfOrFallback(
|
||||
get() = DisplayMode.valueOfOrFallback(
|
||||
sharedPrefs.getString(
|
||||
Keys.KEY_LIBRARY_DISPLAY_MODE,
|
||||
DisplayMode.SHOW_ARTISTS.toString()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val doAudioFocus: Boolean
|
||||
get() = sharedPrefs.getBoolean(Keys.KEY_AUDIO_FOCUS, true)
|
||||
|
@ -66,6 +65,14 @@ class SettingsManager private constructor(context: Context) :
|
|||
val doPlugMgt: Boolean
|
||||
get() = sharedPrefs.getBoolean(Keys.KEY_PLUG_MANAGEMENT, true)
|
||||
|
||||
val songPlaybackMode: PlaybackMode
|
||||
get() = PlaybackMode.valueOfOrFallback(
|
||||
sharedPrefs.getString(
|
||||
Keys.KEY_SONG_PLAYBACK_MODE,
|
||||
PlaybackMode.ALL_SONGS.toString()
|
||||
)
|
||||
)
|
||||
|
||||
var librarySortMode: SortMode
|
||||
get() {
|
||||
return SortMode.fromInt(
|
||||
|
@ -153,6 +160,7 @@ class SettingsManager private constructor(context: Context) :
|
|||
const val KEY_LIBRARY_DISPLAY_MODE = "KEY_LIBRARY_DISPLAY_MODE"
|
||||
const val KEY_AUDIO_FOCUS = "KEY_AUDIO_FOCUS"
|
||||
const val KEY_PLUG_MANAGEMENT = "KEY_PLUG_MGT"
|
||||
const val KEY_SONG_PLAYBACK_MODE = "KEY_SONG_PLAY_MODE"
|
||||
|
||||
const val KEY_LIBRARY_SORT_MODE = "KEY_LIBRARY_SORT_MODE"
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.oxycblt.auxio.R
|
|||
import org.oxycblt.auxio.databinding.FragmentSongsBinding
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.ui.setupSongActions
|
||||
import kotlin.math.ceil
|
||||
|
||||
|
@ -42,10 +42,11 @@ class SongsFragment : Fragment() {
|
|||
val binding = FragmentSongsBinding.inflate(inflater)
|
||||
|
||||
val musicStore = MusicStore.getInstance()
|
||||
val settingsManager = SettingsManager.getInstance()
|
||||
|
||||
val songAdapter = SongsAdapter(
|
||||
musicStore.songs,
|
||||
doOnClick = { playbackModel.playSong(it, PlaybackMode.ALL_SONGS) },
|
||||
doOnClick = { playbackModel.playSong(it, settingsManager.songPlaybackMode) },
|
||||
doOnLongClick = { data, view ->
|
||||
PopupMenu(requireContext(), view).setupSongActions(
|
||||
data, requireContext(), playbackModel
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.os.Build
|
|||
import android.text.SpannableString
|
||||
import android.text.Spanned
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.util.Log
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
|
@ -26,6 +27,7 @@ import org.oxycblt.auxio.music.Genre
|
|||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
|
||||
// Functions for managing UI elements [Not Colors]
|
||||
|
||||
|
@ -108,6 +110,8 @@ fun Window.handleTransparentSystemBars(config: Configuration) {
|
|||
* Show actions for a song item, such as the ones found in [org.oxycblt.auxio.songs.SongsFragment]
|
||||
*/
|
||||
fun PopupMenu.setupSongActions(song: Song, context: Context, playbackModel: PlaybackViewModel) {
|
||||
inflateAndShow(R.menu.menu_song_actions)
|
||||
|
||||
setOnMenuItemClickListener {
|
||||
when (it.itemId) {
|
||||
R.id.action_queue_add -> {
|
||||
|
@ -126,14 +130,34 @@ fun PopupMenu.setupSongActions(song: Song, context: Context, playbackModel: Play
|
|||
true
|
||||
}
|
||||
|
||||
R.id.action_play_all_songs -> {
|
||||
playbackModel.playSong(song, PlaybackMode.ALL_SONGS)
|
||||
true
|
||||
}
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
inflateAndShow(R.menu.menu_song_actions)
|
||||
|
||||
val settingsManager = SettingsManager.getInstance()
|
||||
|
||||
// Find the action that is redundant from the menu and hide it.
|
||||
val idToRemove = when (settingsManager.songPlaybackMode) {
|
||||
PlaybackMode.ALL_SONGS -> R.id.action_play_all_songs
|
||||
PlaybackMode.IN_ARTIST -> R.id.action_play_artist
|
||||
PlaybackMode.IN_ALBUM -> R.id.action_play_album
|
||||
|
||||
else -> -1
|
||||
}
|
||||
|
||||
Log.d(this::class.simpleName, (idToRemove == R.id.action_play_album).toString())
|
||||
|
||||
menu.findItem(idToRemove)?.isVisible = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Show actions for a song item, such as the ones found in [org.oxycblt.auxio.songs.SongsFragment]
|
||||
* Show actions for a album song item, such as the ones found in
|
||||
* [org.oxycblt.auxio.detail.AlbumDetailFragment]
|
||||
*/
|
||||
fun PopupMenu.setupAlbumSongActions(
|
||||
song: Song,
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
android:id="@+id/action_queue_add"
|
||||
android:title="@string/label_queue_add"
|
||||
android:icon="@drawable/ic_queue_add" />
|
||||
<item
|
||||
android:id="@+id/action_play_all_songs"
|
||||
android:title="@string/label_play_all_songs"
|
||||
android:icon="@drawable/ic_song" />
|
||||
<item
|
||||
android:id="@+id/action_play_artist"
|
||||
android:title="@string/label_play_artist"
|
||||
|
|
|
@ -23,4 +23,16 @@
|
|||
<item>SHOW_ARTISTS</item>
|
||||
<item>SHOW_ALBUMS</item>
|
||||
</array>
|
||||
|
||||
<array name="song_playback_mode_entries">
|
||||
<item>@string/label_play_all_songs</item>
|
||||
<item>@string/label_play_artist</item>
|
||||
<item>@string/label_play_album</item>
|
||||
</array>
|
||||
|
||||
<array name="song_playback_mode_values">
|
||||
<item>ALL_SONGS</item>
|
||||
<item>IN_ARTIST</item>
|
||||
<item>IN_ALBUM</item>
|
||||
</array>
|
||||
</resources>
|
|
@ -23,8 +23,9 @@
|
|||
|
||||
<string name="label_play">Play</string>
|
||||
<string name="label_shuffle">Shuffle</string>
|
||||
<string name="label_play_artist">Play from artist</string>
|
||||
<string name="label_play_all_songs">Play from all songs</string>
|
||||
<string name="label_play_album">Play from album</string>
|
||||
<string name="label_play_artist">Play from artist</string>
|
||||
<string name="label_go_artist">Go to artist</string>
|
||||
|
||||
<string name="label_queue">Queue</string>
|
||||
|
@ -38,30 +39,37 @@
|
|||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="setting_title">Settings</string>
|
||||
<string name="setting_ui">Appearance</string>
|
||||
|
||||
<string name="setting_theme">Theme</string>
|
||||
<string name="setting_theme_auto">Automatic</string>
|
||||
<string name="setting_theme_day">Light</string>
|
||||
<string name="setting_theme_night">Dark</string>
|
||||
|
||||
<string name="setting_accent">Accent</string>
|
||||
<string name="setting_accent_unknown">Unknown Accent</string>
|
||||
|
||||
<string name="setting_edge">Edge-To-Edge</string>
|
||||
<string name="setting_edge_desc_on">Edge-to-edge is enabled</string>
|
||||
<string name="setting_edge_desc_off">Edge-to-edge is disabled</string>
|
||||
<string name="setting_edge_desc">Enable edge-to-edge</string>
|
||||
<string name="setting_display">Display</string>
|
||||
|
||||
<string name="setting_lib_display">Library Items</string>
|
||||
|
||||
<string name="setting_color_notif">Colorize notification</string>]
|
||||
<string name="setting_color_desc_on">Show album art on notification</string>
|
||||
<string name="setting_color_desc_off">Hide album art on notification</string>
|
||||
<string name="setting_color_desc">Show album art on notification</string>
|
||||
|
||||
<string name="setting_use_alt_action">Use alternate notification action</string>
|
||||
<string name="setting_use_alt_loop">Prefer repeat mode action</string>
|
||||
<string name="setting_use_alt_shuffle">Prefer shuffle action</string>
|
||||
|
||||
<string name="setting_playback">Audio</string>
|
||||
<string name="setting_playback_audio_focus">Audio focus</string>
|
||||
<string name="setting_playback_focus_desc_on">Audio focus is enabled</string>
|
||||
<string name="setting_playback_focus_desc_off">Audio focus is disabled</string>
|
||||
<string name="setting_playback_focus_desc">Pause when other audio plays [ex. Alarms]</string>
|
||||
|
||||
<string name="setting_playback_plug_mgt">Headset plug management</string>
|
||||
<string name="setting_playback_plug_mgt_desc_on">Headset plug management is enabled</string>
|
||||
<string name="setting_playback_plug_mgt_desc_off">Headset plug management is disabled</string>
|
||||
<string name="setting_playback_plug_mgt_desc">Play/Pause when headset connection changes</string>
|
||||
|
||||
<string name="setting_behavior">Behavior</string>
|
||||
<string name="setting_behavior_song_play">When a song is selected</string>
|
||||
|
||||
<!-- Debug Namespace | Debug labels -->
|
||||
<string name="debug_state_saved">State saved</string>
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
<SwitchPreferenceCompat
|
||||
app:key="KEY_EDGE"
|
||||
android:title="@string/setting_edge"
|
||||
app:summaryOn="@string/setting_edge_desc_on"
|
||||
app:summaryOff="@string/setting_edge_desc_off"
|
||||
app:summary="@string/setting_edge_desc"
|
||||
app:iconSpaceReserved="false"
|
||||
app:allowDividerBelow="false"
|
||||
app:defaultValue="false" />
|
||||
|
@ -45,8 +44,7 @@
|
|||
<SwitchPreferenceCompat
|
||||
app:key="KEY_COLOR_NOTIF"
|
||||
android:title="@string/setting_color_notif"
|
||||
app:summaryOn="@string/setting_color_desc_on"
|
||||
app:summaryOff="@string/setting_color_desc_off"
|
||||
app:summary="@string/setting_color_desc"
|
||||
app:iconSpaceReserved="false"
|
||||
app:defaultValue="true" />
|
||||
|
||||
|
@ -70,15 +68,30 @@
|
|||
android:title="@string/setting_playback_audio_focus"
|
||||
app:iconSpaceReserved="false"
|
||||
app:defaultValue="true"
|
||||
app:summaryOn="@string/setting_playback_focus_desc_on"
|
||||
app:summaryOff="@string/setting_playback_focus_desc_off" />
|
||||
app:summary="@string/setting_playback_focus_desc" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
app:key="KEY_PLUG_MGT"
|
||||
android:title="@string/setting_playback_plug_mgt"
|
||||
app:iconSpaceReserved="false"
|
||||
app:defaultValue="true"
|
||||
app:summaryOn="@string/setting_playback_plug_mgt_desc_on"
|
||||
app:summaryOff="@string/setting_playback_plug_mgt_desc_off" />
|
||||
app:allowDividerBelow="false"
|
||||
app:summary="@string/setting_playback_plug_mgt_desc" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/setting_behavior"
|
||||
android:layout="@layout/item_header">
|
||||
|
||||
<ListPreference
|
||||
app:key="KEY_SONG_PLAY_MODE"
|
||||
android:title="@string/setting_behavior_song_play"
|
||||
app:defaultValue="ALL_SONGS"
|
||||
app:entries="@array/song_playback_mode_entries"
|
||||
app:entryValues="@array/song_playback_mode_values"
|
||||
app:iconSpaceReserved="false"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
|
@ -36,8 +36,7 @@
|
|||
<SwitchPreferenceCompat
|
||||
app:key="KEY_COLOR_NOTIF"
|
||||
android:title="@string/setting_color_notif"
|
||||
app:summaryOn="@string/setting_color_desc_on"
|
||||
app:summaryOff="@string/setting_color_desc_off"
|
||||
app:summary="@string/setting_color_desc"
|
||||
app:iconSpaceReserved="false"
|
||||
app:defaultValue="true" />
|
||||
|
||||
|
@ -61,15 +60,29 @@
|
|||
android:title="@string/setting_playback_audio_focus"
|
||||
app:iconSpaceReserved="false"
|
||||
app:defaultValue="true"
|
||||
app:summaryOn="@string/setting_playback_focus_desc_on"
|
||||
app:summaryOff="@string/setting_playback_focus_desc_off" />
|
||||
app:summary="@string/setting_playback_focus_desc" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
app:key="KEY_PLUG_MGT"
|
||||
android:title="@string/setting_playback_plug_mgt"
|
||||
app:iconSpaceReserved="false"
|
||||
app:defaultValue="true"
|
||||
app:summaryOn="@string/setting_playback_plug_mgt_desc_on"
|
||||
app:summaryOff="@string/setting_playback_plug_mgt_desc_off" />
|
||||
app:allowDividerBelow="false"
|
||||
app:summary="@string/setting_playback_plug_mgt_desc" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/setting_behavior"
|
||||
android:layout="@layout/item_header">
|
||||
|
||||
<ListPreference
|
||||
app:key="KEY_SONG_PLAY_MODE"
|
||||
android:title="@string/setting_behavior_song_play"
|
||||
app:defaultValue="ALL_SONGS"
|
||||
app:entries="@array/song_playback_mode_entries"
|
||||
app:entryValues="@array/song_playback_mode_values"
|
||||
app:iconSpaceReserved="false"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
Loading…
Reference in a new issue