Minor Fixes
Fix some issues with playback, album detail, and other things in the app
This commit is contained in:
parent
dbd2c022a0
commit
60750d976b
10 changed files with 51 additions and 34 deletions
|
|
@ -86,8 +86,4 @@ class MainActivity : AppCompatActivity() {
|
||||||
handleTransparentSystemBars(resources.configuration)
|
handleTransparentSystemBars(resources.configuration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doThemeRecreate(newTheme: Int) {
|
|
||||||
AppCompatDelegate.setDefaultNightMode(newTheme)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import org.oxycblt.auxio.ui.getTransparentAccent
|
||||||
import org.oxycblt.auxio.ui.toColor
|
import org.oxycblt.auxio.ui.toColor
|
||||||
import kotlin.IllegalArgumentException
|
import kotlin.IllegalArgumentException
|
||||||
|
|
||||||
// TODO: Dedicated Search Tab?
|
|
||||||
class MainFragment : Fragment() {
|
class MainFragment : Fragment() {
|
||||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||||
private val detailModel: DetailViewModel by activityViewModels()
|
private val detailModel: DetailViewModel by activityViewModels()
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ class PlaybackStateDatabase(context: Context) :
|
||||||
val database = writableDatabase
|
val database = writableDatabase
|
||||||
|
|
||||||
var state: PlaybackState? = null
|
var state: PlaybackState? = null
|
||||||
var stateCursor: Cursor? = null
|
val stateCursor: Cursor
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stateCursor = database.query(
|
stateCursor = database.query(
|
||||||
|
|
@ -161,7 +161,6 @@ class PlaybackStateDatabase(context: Context) :
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
stateCursor?.close()
|
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -230,7 +229,7 @@ class PlaybackStateDatabase(context: Context) :
|
||||||
val database = readableDatabase
|
val database = readableDatabase
|
||||||
|
|
||||||
val queueItems = mutableListOf<QueueItem>()
|
val queueItems = mutableListOf<QueueItem>()
|
||||||
var queueCursor: Cursor? = null
|
val queueCursor: Cursor
|
||||||
|
|
||||||
try {
|
try {
|
||||||
queueCursor = database.query(
|
queueCursor = database.query(
|
||||||
|
|
@ -258,8 +257,6 @@ class PlaybackStateDatabase(context: Context) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
queueCursor?.close()
|
|
||||||
|
|
||||||
return queueItems
|
return queueItems
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import androidx.navigation.fragment.navArgs
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentAlbumDetailBinding
|
import org.oxycblt.auxio.databinding.FragmentAlbumDetailBinding
|
||||||
import org.oxycblt.auxio.detail.adapters.AlbumSongAdapter
|
import org.oxycblt.auxio.detail.adapters.AlbumSongAdapter
|
||||||
|
import org.oxycblt.auxio.music.Album
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
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
|
||||||
|
|
@ -110,6 +111,13 @@ class AlbumDetailFragment : DetailFragment() {
|
||||||
binding.albumSortButton.disable(requireContext())
|
binding.albumSortButton.disable(requireContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this fragment was created in order to nav to an item, then snap scroll to that item.
|
||||||
|
playbackModel.navToItem.value?.let {
|
||||||
|
if (it is Song) {
|
||||||
|
scrollToPlayingItem(binding, smooth = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -- VIEWMODEL SETUP ---
|
// -- VIEWMODEL SETUP ---
|
||||||
|
|
||||||
detailModel.albumSortMode.observe(viewLifecycleOwner) { mode ->
|
detailModel.albumSortMode.observe(viewLifecycleOwner) { mode ->
|
||||||
|
|
@ -169,25 +177,10 @@ class AlbumDetailFragment : DetailFragment() {
|
||||||
playbackModel.navToItem.observe(viewLifecycleOwner) {
|
playbackModel.navToItem.observe(viewLifecycleOwner) {
|
||||||
if (it != null) {
|
if (it != null) {
|
||||||
if (it is Song) {
|
if (it is Song) {
|
||||||
// Calculate where the item for the currently played song is, and navigate to there.
|
scrollToPlayingItem(binding, smooth = true)
|
||||||
val pos = detailModel.albumSortMode.value!!.getSortedSongList(
|
|
||||||
detailModel.currentAlbum.value!!.songs
|
|
||||||
).indexOf(playbackModel.song.value)
|
|
||||||
|
|
||||||
if (pos != -1) {
|
|
||||||
binding.albumSongRecycler.post {
|
|
||||||
// Only scroll after UI creation
|
|
||||||
val y = binding.albumSongRecycler.y +
|
|
||||||
binding.albumSongRecycler.getChildAt(pos).y
|
|
||||||
|
|
||||||
binding.nestedScroll.scrollTo(0, y.toInt())
|
|
||||||
}
|
|
||||||
|
|
||||||
playbackModel.doneWithNavToItem()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detailModel.currentAlbum.value!!.id == playbackModel.song.value!!.album.id) {
|
if (it is Album && it.id == detailModel.currentAlbum.value!!.id) {
|
||||||
playbackModel.doneWithNavToItem()
|
playbackModel.doneWithNavToItem()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -197,4 +190,31 @@ class AlbumDetailFragment : DetailFragment() {
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the position and and scroll to a currently playing item.
|
||||||
|
* @param binding The binding required
|
||||||
|
* @param smooth Whether to scroll smoothly or not, true for yes, false for no.
|
||||||
|
*/
|
||||||
|
private fun scrollToPlayingItem(binding: FragmentAlbumDetailBinding, smooth: Boolean) {
|
||||||
|
// Calculate where the item for the currently played song is, and scroll to there
|
||||||
|
val pos = detailModel.albumSortMode.value!!.getSortedSongList(
|
||||||
|
detailModel.currentAlbum.value!!.songs
|
||||||
|
).indexOf(playbackModel.song.value)
|
||||||
|
|
||||||
|
if (pos != -1) {
|
||||||
|
binding.albumSongRecycler.post {
|
||||||
|
val y = binding.albumSongRecycler.y +
|
||||||
|
binding.albumSongRecycler.getChildAt(pos).y
|
||||||
|
|
||||||
|
if (smooth) {
|
||||||
|
binding.nestedScroll.smoothScrollTo(0, y.toInt())
|
||||||
|
} else {
|
||||||
|
binding.nestedScroll.scrollTo(0, y.toInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
playbackModel.doneWithNavToItem()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,7 @@ import androidx.navigation.fragment.findNavController
|
||||||
* A Base [Fragment] implementing a [OnBackPressedCallback] so that Auxio will navigate upwards
|
* A Base [Fragment] implementing a [OnBackPressedCallback] so that Auxio will navigate upwards
|
||||||
* instead of out of the app if a Detail Fragment is currently open. Also carries the
|
* instead of out of the app if a Detail Fragment is currently open. Also carries the
|
||||||
* multi-navigation fix.
|
* multi-navigation fix.
|
||||||
* TODO: Implement a system where the Toolbar will update with some info when
|
* TODO: Migrate to a more powerful/efficient CoordinatorLayout instead of NestedScrollView
|
||||||
* the main detail header is obscured.
|
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
abstract class DetailFragment : Fragment() {
|
abstract class DetailFragment : Fragment() {
|
||||||
|
|
@ -38,7 +37,7 @@ abstract class DetailFragment : Fragment() {
|
||||||
|
|
||||||
override fun handleOnBackPressed() {
|
override fun handleOnBackPressed() {
|
||||||
val navController = findNavController()
|
val navController = findNavController()
|
||||||
// Check if it's the root of nested fragments in this navhost
|
// Check if it's the root of nested fragments in this NavHost
|
||||||
if (navController.currentDestination?.id == navController.graph.startDestination) {
|
if (navController.currentDestination?.id == navController.graph.startDestination) {
|
||||||
isEnabled = false
|
isEnabled = false
|
||||||
requireActivity().onBackPressed()
|
requireActivity().onBackPressed()
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,11 @@ import org.oxycblt.auxio.ui.setupArtistActions
|
||||||
import org.oxycblt.auxio.ui.setupGenreActions
|
import org.oxycblt.auxio.ui.setupGenreActions
|
||||||
import org.oxycblt.auxio.ui.setupSongActions
|
import org.oxycblt.auxio.ui.setupSongActions
|
||||||
|
|
||||||
// A Fragment to show all the music in the Library.
|
/**
|
||||||
|
* A [Fragment] that shows a custom list of [Genre], [Artist], or [Album] data. Also allows for
|
||||||
|
* search functionality.
|
||||||
|
* TODO: Move search to separate tab?
|
||||||
|
*/
|
||||||
class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
||||||
|
|
||||||
private val libraryModel: LibraryViewModel by activityViewModels()
|
private val libraryModel: LibraryViewModel by activityViewModels()
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,9 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
queueMenuItem = menu.findItem(R.id.action_queue)
|
queueMenuItem = menu.findItem(R.id.action_queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make ellipsizing of song title work
|
||||||
|
binding.playbackSong.isSelected = true
|
||||||
|
|
||||||
binding.playbackSeekBar.setOnSeekBarChangeListener(this)
|
binding.playbackSeekBar.setOnSeekBarChangeListener(this)
|
||||||
|
|
||||||
// --- VIEWMODEL SETUP --
|
// --- VIEWMODEL SETUP --
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ class QueueFragment : Fragment() {
|
||||||
// Since QueueFragment doesn't fit system windows, inset padding needs to be
|
// Since QueueFragment doesn't fit system windows, inset padding needs to be
|
||||||
// artificially applied to the Toolbar so that it fits on the main window AND
|
// artificially applied to the Toolbar so that it fits on the main window AND
|
||||||
// so that the elevation doesn't show on the top.
|
// so that the elevation doesn't show on the top.
|
||||||
setOnApplyWindowInsetsListener { _, insets ->
|
setOnApplyWindowInsetsListener @Suppress("DEPRECATION") { _, insets ->
|
||||||
val top = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
val top = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
insets.getInsets(WindowInsets.Type.systemBars()).top
|
insets.getInsets(WindowInsets.Type.systemBars()).top
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -457,7 +457,6 @@ class PlaybackStateManager private constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- PERSISTENCE FUNCTIONS ---
|
// --- PERSISTENCE FUNCTIONS ---
|
||||||
// TODO: Implement a fast queue save function
|
|
||||||
|
|
||||||
suspend fun saveStateToDatabase(context: Context) {
|
suspend fun saveStateToDatabase(context: Context) {
|
||||||
Log.d(this::class.simpleName, "Saving state to DB.")
|
Log.d(this::class.simpleName, "Saving state to DB.")
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@
|
||||||
<string name="format_double_info">%1$s / %2$s / %3$s</string>
|
<string name="format_double_info">%1$s / %2$s / %3$s</string>
|
||||||
<string name="format_double_counts">%1$s, %2$s</string>
|
<string name="format_double_counts">%1$s, %2$s</string>
|
||||||
<string name="format_next_from">Next From: %s</string>
|
<string name="format_next_from">Next From: %s</string>
|
||||||
<string name="format_accent_summary"><b>%1s</b>: %2s</string>
|
<string name="format_accent_summary"><b>%1$s</b>: %2$s</string>
|
||||||
|
|
||||||
<plurals name="format_song_count">
|
<plurals name="format_song_count">
|
||||||
<item quantity="one">%s Song</item>
|
<item quantity="one">%s Song</item>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue