diff --git a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt index 356c3efc6..ee0419f5d 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt @@ -86,8 +86,4 @@ class MainActivity : AppCompatActivity() { handleTransparentSystemBars(resources.configuration) } } - - private fun doThemeRecreate(newTheme: Int) { - AppCompatDelegate.setDefaultNightMode(newTheme) - } } diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index cc7f8f29f..a207cbe1b 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -25,7 +25,6 @@ import org.oxycblt.auxio.ui.getTransparentAccent import org.oxycblt.auxio.ui.toColor import kotlin.IllegalArgumentException -// TODO: Dedicated Search Tab? class MainFragment : Fragment() { private val playbackModel: PlaybackViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() diff --git a/app/src/main/java/org/oxycblt/auxio/database/PlaybackStateDatabase.kt b/app/src/main/java/org/oxycblt/auxio/database/PlaybackStateDatabase.kt index db48cefba..5088c1f9b 100644 --- a/app/src/main/java/org/oxycblt/auxio/database/PlaybackStateDatabase.kt +++ b/app/src/main/java/org/oxycblt/auxio/database/PlaybackStateDatabase.kt @@ -119,7 +119,7 @@ class PlaybackStateDatabase(context: Context) : val database = writableDatabase var state: PlaybackState? = null - var stateCursor: Cursor? = null + val stateCursor: Cursor try { stateCursor = database.query( @@ -161,7 +161,6 @@ class PlaybackStateDatabase(context: Context) : ) } } finally { - stateCursor?.close() return state } } @@ -230,7 +229,7 @@ class PlaybackStateDatabase(context: Context) : val database = readableDatabase val queueItems = mutableListOf() - var queueCursor: Cursor? = null + val queueCursor: Cursor try { queueCursor = database.query( @@ -258,8 +257,6 @@ class PlaybackStateDatabase(context: Context) : } } } finally { - queueCursor?.close() - return queueItems } } 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 621716f07..dfacfb7c1 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -12,6 +12,7 @@ import androidx.navigation.fragment.navArgs import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentAlbumDetailBinding import org.oxycblt.auxio.detail.adapters.AlbumSongAdapter +import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel @@ -110,6 +111,13 @@ class AlbumDetailFragment : DetailFragment() { 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 --- detailModel.albumSortMode.observe(viewLifecycleOwner) { mode -> @@ -169,25 +177,10 @@ class AlbumDetailFragment : DetailFragment() { playbackModel.navToItem.observe(viewLifecycleOwner) { if (it != null) { if (it is Song) { - // Calculate where the item for the currently played song is, and navigate to there. - 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() - } + scrollToPlayingItem(binding, smooth = true) } - if (detailModel.currentAlbum.value!!.id == playbackModel.song.value!!.album.id) { + if (it is Album && it.id == detailModel.currentAlbum.value!!.id) { playbackModel.doneWithNavToItem() } } @@ -197,4 +190,31 @@ class AlbumDetailFragment : DetailFragment() { 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() + } + } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt index 1338e0bba..19827e3f8 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt @@ -11,8 +11,7 @@ import androidx.navigation.fragment.findNavController * 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 * multi-navigation fix. - * TODO: Implement a system where the Toolbar will update with some info when - * the main detail header is obscured. + * TODO: Migrate to a more powerful/efficient CoordinatorLayout instead of NestedScrollView * @author OxygenCobalt */ abstract class DetailFragment : Fragment() { @@ -38,7 +37,7 @@ abstract class DetailFragment : Fragment() { override fun handleOnBackPressed() { 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) { isEnabled = false requireActivity().onBackPressed() 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 fa16118fd..48445f779 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt @@ -34,7 +34,11 @@ import org.oxycblt.auxio.ui.setupArtistActions import org.oxycblt.auxio.ui.setupGenreActions 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 { private val libraryModel: LibraryViewModel by activityViewModels() 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 79520a23c..689f85a9a 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt @@ -83,6 +83,9 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener { queueMenuItem = menu.findItem(R.id.action_queue) } + // Make ellipsizing of song title work + binding.playbackSong.isSelected = true + binding.playbackSeekBar.setOnSeekBarChangeListener(this) // --- VIEWMODEL SETUP -- diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt index 88c541c44..bd3a0f32e 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt @@ -53,7 +53,7 @@ class QueueFragment : Fragment() { // 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 // 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) { insets.getInsets(WindowInsets.Type.systemBars()).top } else { 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 b5973b950..c7d80dfdb 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 @@ -457,7 +457,6 @@ class PlaybackStateManager private constructor() { } // --- PERSISTENCE FUNCTIONS --- - // TODO: Implement a fast queue save function suspend fun saveStateToDatabase(context: Context) { Log.d(this::class.simpleName, "Saving state to DB.") diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6f2312480..882eb2ce5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -126,7 +126,7 @@ %1$s / %2$s / %3$s %1$s, %2$s Next From: %s - <b>%1s</b>: %2s + <b>%1$s</b>: %2$s %s Song