Minor changes
Change some minor things across the app.
This commit is contained in:
parent
034f073bac
commit
6ce8c854a9
27 changed files with 112 additions and 104 deletions
|
@ -1,7 +1,7 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
apply plugin: "androidx.navigation.safeargs"
|
apply plugin: 'androidx.navigation.safeargs'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 30
|
compileSdkVersion 30
|
||||||
|
@ -22,6 +22,10 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
debug {
|
||||||
|
applicationIdSuffix = '.debug'
|
||||||
|
versionNameSuffix = "-DEBUG"
|
||||||
|
}
|
||||||
release {
|
release {
|
||||||
minifyEnabled true
|
minifyEnabled true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
|
|
@ -11,9 +11,8 @@ 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]
|
||||||
// FIXME: Compat issues with Versions 5/6 that cause recyclerview
|
// TODO: Landscape UI layouts
|
||||||
// dividers not to show and for progress bars to look wonky
|
// FIXME: Compat issue with Versions 5 that leads to progress bar looking off
|
||||||
// FIXME: Navigation memory leak that is really confusing
|
|
||||||
class MainActivity : AppCompatActivity(R.layout.activity_main) {
|
class MainActivity : AppCompatActivity(R.layout.activity_main) {
|
||||||
|
|
||||||
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
|
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
|
||||||
|
|
|
@ -59,9 +59,9 @@ class MainFragment : Fragment() {
|
||||||
)
|
)
|
||||||
|
|
||||||
val navController = (
|
val navController = (
|
||||||
childFragmentManager.findFragmentById(R.id.explore_nav_host)
|
childFragmentManager.findFragmentById(R.id.explore_nav_host)
|
||||||
as NavHostFragment?
|
as NavHostFragment?
|
||||||
)?.findNavController()
|
)?.findNavController()
|
||||||
|
|
||||||
// --- UI SETUP ---
|
// --- UI SETUP ---
|
||||||
|
|
||||||
|
@ -97,11 +97,11 @@ class MainFragment : Fragment() {
|
||||||
if (it) {
|
if (it) {
|
||||||
if (binding.navBar.selectedItemId != R.id.library_fragment ||
|
if (binding.navBar.selectedItemId != R.id.library_fragment ||
|
||||||
(
|
(
|
||||||
navController!!.currentDestination?.id == R.id.album_detail_fragment &&
|
navController!!.currentDestination?.id == R.id.album_detail_fragment &&
|
||||||
detailModel.currentAlbum.value == null ||
|
detailModel.currentAlbum.value == null ||
|
||||||
detailModel.currentAlbum.value?.id
|
detailModel.currentAlbum.value?.id
|
||||||
!= playbackModel.song.value!!.album.id
|
!= playbackModel.song.value!!.album.id
|
||||||
) ||
|
) ||
|
||||||
navController.currentDestination?.id == R.id.artist_detail_fragment ||
|
navController.currentDestination?.id == R.id.artist_detail_fragment ||
|
||||||
navController.currentDestination?.id == R.id.genre_detail_fragment
|
navController.currentDestination?.id == R.id.genre_detail_fragment
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import android.util.Log
|
||||||
*/
|
*/
|
||||||
class PlaybackStateDatabase(context: Context) :
|
class PlaybackStateDatabase(context: Context) :
|
||||||
SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) {
|
SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) {
|
||||||
|
|
||||||
override fun onCreate(db: SQLiteDatabase) {
|
override fun onCreate(db: SQLiteDatabase) {
|
||||||
createTable(db, TABLE_NAME_STATE)
|
createTable(db, TABLE_NAME_STATE)
|
||||||
createTable(db, TABLE_NAME_QUEUE)
|
createTable(db, TABLE_NAME_QUEUE)
|
||||||
|
@ -111,7 +112,7 @@ class PlaybackStateDatabase(context: Context) :
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the stored [PlaybackState] from the database, if there is one.
|
* Read the stored [PlaybackState] from the database, if there is one.
|
||||||
* @return The stored [PlaybackState], null if there isnt one,.
|
* @return The stored [PlaybackState], null if there isn't one,.
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
fun readState(): PlaybackState? {
|
fun readState(): PlaybackState? {
|
||||||
|
@ -121,7 +122,11 @@ class PlaybackStateDatabase(context: Context) :
|
||||||
var stateCursor: Cursor? = null
|
var stateCursor: Cursor? = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stateCursor = database.query(TABLE_NAME_STATE, null, null, null, null, null, null)
|
stateCursor = database.query(
|
||||||
|
TABLE_NAME_STATE,
|
||||||
|
null, null, null,
|
||||||
|
null, null, null
|
||||||
|
)
|
||||||
|
|
||||||
stateCursor?.use { cursor ->
|
stateCursor?.use { cursor ->
|
||||||
// Don't bother if the cursor [and therefore database] has nothing in it.
|
// Don't bother if the cursor [and therefore database] has nothing in it.
|
||||||
|
@ -227,7 +232,10 @@ class PlaybackStateDatabase(context: Context) :
|
||||||
var queueCursor: Cursor? = null
|
var queueCursor: Cursor? = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
queueCursor = database.query(TABLE_NAME_QUEUE, null, null, null, null, null, null)
|
queueCursor = database.query(
|
||||||
|
TABLE_NAME_QUEUE, null, null,
|
||||||
|
null, null, null, null
|
||||||
|
)
|
||||||
|
|
||||||
queueCursor?.use { cursor ->
|
queueCursor?.use { cursor ->
|
||||||
if (cursor.count == 0) return@use
|
if (cursor.count == 0) return@use
|
||||||
|
|
|
@ -131,7 +131,7 @@ class AlbumDetailFragment : DetailFragment() {
|
||||||
binding.albumSongRecycler.post {
|
binding.albumSongRecycler.post {
|
||||||
// Only scroll after UI creation
|
// Only scroll after UI creation
|
||||||
val y = binding.albumSongRecycler.y +
|
val y = binding.albumSongRecycler.y +
|
||||||
binding.albumSongRecycler.getChildAt(pos).y
|
binding.albumSongRecycler.getChildAt(pos).y
|
||||||
|
|
||||||
binding.nestedScroll.smoothScrollBy(0, y.toInt())
|
binding.nestedScroll.smoothScrollBy(0, y.toInt())
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,8 @@ 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: Merge headers with recyclerview [if possible]
|
* TODO: Implement a system where the Toolbar will update with some info when
|
||||||
|
* the main detail header is obscured.
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
abstract class DetailFragment : Fragment() {
|
abstract class DetailFragment : Fragment() {
|
||||||
|
@ -32,6 +33,7 @@ abstract class DetailFragment : Fragment() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
callback.isEnabled = false
|
callback.isEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private val callback = object : OnBackPressedCallback(false) {
|
private val callback = object : OnBackPressedCallback(false) {
|
||||||
|
|
||||||
override fun handleOnBackPressed() {
|
override fun handleOnBackPressed() {
|
||||||
|
|
|
@ -9,9 +9,6 @@ import org.oxycblt.auxio.music.Genre
|
||||||
import org.oxycblt.auxio.recycler.SortMode
|
import org.oxycblt.auxio.recycler.SortMode
|
||||||
|
|
||||||
// ViewModel for the Detail Fragments.
|
// ViewModel for the Detail Fragments.
|
||||||
// TODO:
|
|
||||||
// - Implement a system where the Toolbar will update with some info when
|
|
||||||
// the main detail header is obscured.
|
|
||||||
class DetailViewModel : ViewModel() {
|
class DetailViewModel : ViewModel() {
|
||||||
private var mIsNavigating = false
|
private var mIsNavigating = false
|
||||||
val isNavigating: Boolean get() = mIsNavigating
|
val isNavigating: Boolean get() = mIsNavigating
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding
|
import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding
|
||||||
import org.oxycblt.auxio.music.Album
|
import org.oxycblt.auxio.music.Album
|
||||||
import org.oxycblt.auxio.recycler.DiffCallback
|
import org.oxycblt.auxio.recycler.DiffCallback
|
||||||
|
@ -11,17 +12,19 @@ import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
|
||||||
|
|
||||||
class DetailAlbumAdapter(
|
class DetailAlbumAdapter(
|
||||||
private val doOnClick: (data: Album) -> Unit,
|
private val doOnClick: (data: Album) -> Unit,
|
||||||
private val doOnLongClick: (data: Album, view: View) -> Unit
|
private val doOnLongClick: (data: Album, view: View) -> Unit,
|
||||||
) : ListAdapter<Album, DetailAlbumAdapter.AlbumViewHolder>(DiffCallback()) {
|
) : ListAdapter<Album, RecyclerView.ViewHolder>(DiffCallback()) {
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AlbumViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
return AlbumViewHolder(
|
return AlbumViewHolder(
|
||||||
ItemArtistAlbumBinding.inflate(LayoutInflater.from(parent.context))
|
ItemArtistAlbumBinding.inflate(LayoutInflater.from(parent.context))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: AlbumViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
holder.bind(getItem(position))
|
when (val item = getItem(position)) {
|
||||||
|
is Album -> (holder as AlbumViewHolder).bind(item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic ViewHolder for a detail album
|
// Generic ViewHolder for a detail album
|
||||||
|
|
|
@ -44,7 +44,7 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
val binding = FragmentLibraryBinding.inflate(inflater)
|
val binding = FragmentLibraryBinding.inflate(inflater)
|
||||||
|
|
||||||
val musicStore = MusicStore.getInstance()
|
val musicStore = MusicStore.getInstance()
|
||||||
|
|
|
@ -107,5 +107,5 @@ class MosaicFetcher(private val context: Context) : Fetcher<List<Uri>> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun key(data: List<Uri>): String? = data.toString()
|
override fun key(data: List<Uri>): String = data.toString()
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ 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.ImageView
|
import android.widget.ImageButton
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
|
@ -27,8 +27,6 @@ import org.oxycblt.auxio.ui.createToast
|
||||||
class CompactPlaybackFragment : Fragment() {
|
class CompactPlaybackFragment : Fragment() {
|
||||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||||
|
|
||||||
private var playbackControls: ImageView? = null
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
@ -77,9 +75,6 @@ class CompactPlaybackFragment : Fragment() {
|
||||||
binding.playbackProgress.progress = it
|
binding.playbackProgress.progress = it
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the playback control ImageView for later.
|
|
||||||
playbackControls = binding.playbackControls
|
|
||||||
|
|
||||||
Log.d(this::class.simpleName, "Fragment Created")
|
Log.d(this::class.simpleName, "Fragment Created")
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
|
@ -90,6 +85,10 @@ class CompactPlaybackFragment : Fragment() {
|
||||||
|
|
||||||
playbackModel.disableAnimation()
|
playbackModel.disableAnimation()
|
||||||
|
|
||||||
|
// Use the caveman method of getting a view as storing the binding will cause a memory
|
||||||
|
// leak.
|
||||||
|
val playbackControls = requireView().findViewById<ImageButton>(R.id.playback_controls)
|
||||||
|
|
||||||
// Observe the changes to isPlaying for
|
// Observe the changes to isPlaying for
|
||||||
val iconPauseToPlay = ContextCompat.getDrawable(
|
val iconPauseToPlay = ContextCompat.getDrawable(
|
||||||
requireContext(), R.drawable.ic_pause_to_play
|
requireContext(), R.drawable.ic_pause_to_play
|
||||||
|
@ -122,10 +121,4 @@ class CompactPlaybackFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
|
|
||||||
playbackControls = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
val binding = FragmentPlaybackBinding.inflate(inflater)
|
val binding = FragmentPlaybackBinding.inflate(inflater)
|
||||||
|
|
||||||
// TODO: Add a swipe-to-next-track function using a ViewPager
|
// TODO: Add a swipe-to-next-track function using a ViewPager
|
||||||
|
@ -84,7 +84,6 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make marquee scroll work
|
// Make marquee scroll work
|
||||||
// TODO: Add nav here as well
|
|
||||||
binding.playbackSong.isSelected = true
|
binding.playbackSong.isSelected = true
|
||||||
binding.playbackSeekBar.setOnSeekBarChangeListener(this)
|
binding.playbackSeekBar.setOnSeekBarChangeListener(this)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.oxycblt.auxio.playback.queue
|
package org.oxycblt.auxio.playback.queue
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
|
@ -54,7 +55,7 @@ class QueueAdapter(
|
||||||
ItemQueueSongBinding.inflate(LayoutInflater.from(parent.context))
|
ItemQueueSongBinding.inflate(LayoutInflater.from(parent.context))
|
||||||
)
|
)
|
||||||
USER_QUEUE_HEADER_ITEM_tYPE -> UserQueueHeaderViewHolder(
|
USER_QUEUE_HEADER_ITEM_tYPE -> UserQueueHeaderViewHolder(
|
||||||
ItemActionHeaderBinding.inflate(LayoutInflater.from(parent.context))
|
parent.context, ItemActionHeaderBinding.inflate(LayoutInflater.from(parent.context))
|
||||||
)
|
)
|
||||||
else -> error("Someone messed with the ViewHolder item types.")
|
else -> error("Someone messed with the ViewHolder item types.")
|
||||||
}
|
}
|
||||||
|
@ -97,6 +98,7 @@ class QueueAdapter(
|
||||||
// Check for two things:
|
// Check for two things:
|
||||||
// If the data from the next queue is now entirely empty [Signified by a header at the end]
|
// If the data from the next queue is now entirely empty [Signified by a header at the end]
|
||||||
// Or if the data from the last queue is now entirely empty [Signified by there being 2 headers with no items in between]
|
// Or if the data from the last queue is now entirely empty [Signified by there being 2 headers with no items in between]
|
||||||
|
// If so, remove that item and the removed item in a range. Otherwise just remove the item.
|
||||||
if (data[data.lastIndex] is Header) {
|
if (data[data.lastIndex] is Header) {
|
||||||
val lastIndex = data.lastIndex
|
val lastIndex = data.lastIndex
|
||||||
|
|
||||||
|
@ -146,8 +148,16 @@ class QueueAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class UserQueueHeaderViewHolder(
|
inner class UserQueueHeaderViewHolder(
|
||||||
|
context: Context,
|
||||||
private val binding: ItemActionHeaderBinding
|
private val binding: ItemActionHeaderBinding
|
||||||
) : BaseViewHolder<Header>(binding, null, null) {
|
) : BaseViewHolder<Header>(binding, null, null) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
binding.headerButton.contentDescription = context.getString(
|
||||||
|
R.string.description_clear_user_queue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onBind(data: Header) {
|
override fun onBind(data: Header) {
|
||||||
binding.header = data
|
binding.header = data
|
||||||
binding.headerButton.apply {
|
binding.headerButton.apply {
|
||||||
|
|
|
@ -28,7 +28,7 @@ class QueueFragment : Fragment() {
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
val binding = FragmentQueueBinding.inflate(inflater)
|
val binding = FragmentQueueBinding.inflate(inflater)
|
||||||
|
|
||||||
val callback = QueueDragCallback(playbackModel)
|
val callback = QueueDragCallback(playbackModel)
|
||||||
|
|
|
@ -560,12 +560,12 @@ class PlaybackStateManager private constructor() {
|
||||||
// Traverse albums and then album songs instead of just the songs, as its faster.
|
// Traverse albums and then album songs instead of just the songs, as its faster.
|
||||||
musicStore.albums.find { it.id == item.albumId }
|
musicStore.albums.find { it.id == item.albumId }
|
||||||
?.songs?.find { it.id == item.songId }?.let {
|
?.songs?.find { it.id == item.songId }?.let {
|
||||||
if (item.isUserQueue) {
|
if (item.isUserQueue) {
|
||||||
mUserQueue.add(it)
|
mUserQueue.add(it)
|
||||||
} else {
|
} else {
|
||||||
mQueue.add(it)
|
mQueue.add(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a more accurate index [At least if were not in the user queue]
|
// Get a more accurate index [At least if were not in the user queue]
|
||||||
|
|
|
@ -3,8 +3,6 @@ package org.oxycblt.auxio.recycler.viewholders
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.annotation.DrawableRes
|
|
||||||
import org.oxycblt.auxio.databinding.ItemActionHeaderBinding
|
|
||||||
import org.oxycblt.auxio.databinding.ItemAlbumBinding
|
import org.oxycblt.auxio.databinding.ItemAlbumBinding
|
||||||
import org.oxycblt.auxio.databinding.ItemArtistBinding
|
import org.oxycblt.auxio.databinding.ItemArtistBinding
|
||||||
import org.oxycblt.auxio.databinding.ItemGenreBinding
|
import org.oxycblt.auxio.databinding.ItemGenreBinding
|
||||||
|
@ -149,20 +147,3 @@ class HeaderViewHolder(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ActionHeaderViewHolder(
|
|
||||||
protected val binding: ItemActionHeaderBinding,
|
|
||||||
@DrawableRes private val iconRes: Int
|
|
||||||
) : BaseViewHolder<Header>(binding, null, null) {
|
|
||||||
override fun onBind(data: Header) {
|
|
||||||
binding.header = data
|
|
||||||
binding.headerButton.apply {
|
|
||||||
setImageResource(iconRes)
|
|
||||||
setOnClickListener {
|
|
||||||
onActionClick()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun onActionClick()
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ class SongsFragment : Fragment() {
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
val binding = FragmentSongsBinding.inflate(inflater)
|
val binding = FragmentSongsBinding.inflate(inflater)
|
||||||
|
|
||||||
val musicStore = MusicStore.getInstance()
|
val musicStore = MusicStore.getInstance()
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Animated icons derived from noice
|
||||||
|
https://github.com/ashutoshgngwr/noice/
|
||||||
|
-->
|
||||||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
android:drawable="@drawable/ic_pause_large">
|
android:drawable="@drawable/ic_pause_large">
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector android:width="32dp"
|
<vector android:width="32dp"
|
||||||
android:height="32dp"
|
android:height="32dp"
|
||||||
android:tint="@color/control_color"
|
android:tint="@color/control_color"
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Animated icons derived from noice
|
||||||
|
https://github.com/ashutoshgngwr/noice/
|
||||||
|
-->
|
||||||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
android:drawable="@drawable/ic_play_large">
|
android:drawable="@drawable/ic_play_large">
|
||||||
|
|
|
@ -9,7 +9,7 @@ https://stackoverflow.com/a/61157571/14143986
|
||||||
android:top="-2dp">
|
android:top="-2dp">
|
||||||
<shape android:shape="rectangle">
|
<shape android:shape="rectangle">
|
||||||
<stroke
|
<stroke
|
||||||
android:width="0.5dp"
|
android:width="1dp"
|
||||||
android:color="@color/divider_color" />
|
android:color="@color/divider_color" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
|
|
4
app/src/main/res/drawable/ui_small_unbounded_ripple.xml
Normal file
4
app/src/main/res/drawable/ui_small_unbounded_ripple.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:color="@color/selection_color"
|
||||||
|
android:radius="@dimen/size_divider_ripple" />
|
|
@ -111,23 +111,23 @@
|
||||||
android:id="@+id/album_song_header"
|
android:id="@+id/album_song_header"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginTop="@dimen/padding_medium"
|
android:layout_marginTop="@dimen/margin_medium"
|
||||||
android:background="@drawable/ui_header_dividers"
|
android:background="@drawable/ui_header_dividers"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
|
||||||
android:fontFamily="@font/inter_semibold"
|
android:fontFamily="@font/inter_semibold"
|
||||||
android:paddingStart="@dimen/padding_medium"
|
android:paddingStart="@dimen/padding_medium"
|
||||||
android:paddingTop="@dimen/padding_small"
|
android:paddingTop="@dimen/padding_small"
|
||||||
android:paddingEnd="@dimen/padding_small"
|
android:paddingEnd="@dimen/padding_small"
|
||||||
android:paddingBottom="@dimen/padding_small"
|
android:paddingBottom="@dimen/padding_small"
|
||||||
android:text="@string/label_songs"
|
android:text="@string/label_songs"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="19sp"
|
android:textSize="19sp"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/album_details" />
|
app:layout_constraintTop_toBottomOf="@+id/album_details"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/album_sort_button"
|
android:id="@+id/album_sort_button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="@dimen/margin_medium"
|
|
||||||
android:background="@drawable/ui_header_dividers"
|
android:background="@drawable/ui_header_dividers"
|
||||||
android:contentDescription="@string/description_sort_button"
|
android:contentDescription="@string/description_sort_button"
|
||||||
android:onClick="@{() -> detailModel.incrementAlbumSortMode()}"
|
android:onClick="@{() -> detailModel.incrementAlbumSortMode()}"
|
||||||
|
@ -135,9 +135,9 @@
|
||||||
android:paddingTop="@dimen/padding_small"
|
android:paddingTop="@dimen/padding_small"
|
||||||
android:paddingEnd="@dimen/margin_medium"
|
android:paddingEnd="@dimen/margin_medium"
|
||||||
android:paddingBottom="@dimen/padding_small"
|
android:paddingBottom="@dimen/padding_small"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/album_song_recycler"
|
app:layout_constraintBottom_toBottomOf="@+id/album_song_header"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/album_details"
|
app:layout_constraintTop_toTopOf="@+id/album_song_header"
|
||||||
tools:src="@drawable/ic_sort_numeric_down" />
|
tools:src="@drawable/ic_sort_numeric_down" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
|
|
@ -104,15 +104,15 @@
|
||||||
android:id="@+id/artist_album_header"
|
android:id="@+id/artist_album_header"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginTop="@dimen/padding_medium"
|
android:layout_marginTop="@dimen/margin_medium"
|
||||||
android:background="@drawable/ui_header_dividers"
|
android:background="@drawable/ui_header_dividers"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
|
||||||
android:fontFamily="@font/inter_semibold"
|
android:fontFamily="@font/inter_semibold"
|
||||||
android:paddingStart="@dimen/padding_medium"
|
android:paddingStart="@dimen/padding_medium"
|
||||||
android:paddingTop="@dimen/padding_small"
|
android:paddingTop="@dimen/padding_small"
|
||||||
android:paddingEnd="@dimen/padding_small"
|
android:paddingEnd="@dimen/padding_small"
|
||||||
android:paddingBottom="@dimen/padding_small"
|
android:paddingBottom="@dimen/padding_small"
|
||||||
android:text="@string/label_albums"
|
android:text="@string/label_albums"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="19sp"
|
android:textSize="19sp"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/artist_counts" />
|
app:layout_constraintTop_toBottomOf="@+id/artist_counts" />
|
||||||
|
|
||||||
|
@ -120,7 +120,6 @@
|
||||||
android:id="@+id/artist_sort_button"
|
android:id="@+id/artist_sort_button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="@dimen/margin_medium"
|
|
||||||
android:background="@drawable/ui_header_dividers"
|
android:background="@drawable/ui_header_dividers"
|
||||||
android:contentDescription="@string/description_sort_button"
|
android:contentDescription="@string/description_sort_button"
|
||||||
android:onClick="@{() -> detailModel.incrementArtistSortMode()}"
|
android:onClick="@{() -> detailModel.incrementArtistSortMode()}"
|
||||||
|
@ -128,9 +127,9 @@
|
||||||
android:paddingTop="@dimen/padding_small"
|
android:paddingTop="@dimen/padding_small"
|
||||||
android:paddingEnd="@dimen/margin_medium"
|
android:paddingEnd="@dimen/margin_medium"
|
||||||
android:paddingBottom="@dimen/padding_small"
|
android:paddingBottom="@dimen/padding_small"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/artist_album_recycler"
|
app:layout_constraintBottom_toBottomOf="@+id/artist_album_header"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/artist_counts"
|
app:layout_constraintTop_toTopOf="@+id/artist_album_header"
|
||||||
tools:src="@drawable/ic_sort_numeric_down" />
|
tools:src="@drawable/ic_sort_numeric_down" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
|
|
@ -121,18 +121,17 @@
|
||||||
android:id="@+id/genre_sort_button"
|
android:id="@+id/genre_sort_button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="@dimen/margin_medium"
|
|
||||||
android:background="@drawable/ui_header_dividers"
|
android:background="@drawable/ui_header_dividers"
|
||||||
android:contentDescription="@string/description_sort_button"
|
android:contentDescription="@string/description_sort_button"
|
||||||
|
android:onClick="@{() -> detailModel.incrementGenreSortMode()}"
|
||||||
android:paddingStart="@dimen/padding_medium"
|
android:paddingStart="@dimen/padding_medium"
|
||||||
android:paddingTop="@dimen/padding_small"
|
android:paddingTop="@dimen/padding_small"
|
||||||
android:paddingEnd="@dimen/margin_medium"
|
android:paddingEnd="@dimen/margin_medium"
|
||||||
android:paddingBottom="@dimen/padding_small"
|
android:paddingBottom="@dimen/padding_small"
|
||||||
android:onClick="@{() -> detailModel.incrementGenreSortMode()}"
|
app:layout_constraintBottom_toBottomOf="@+id/genre_artist_header"
|
||||||
tools:src="@drawable/ic_sort_alpha_down"
|
app:layout_constraintTop_toTopOf="@+id/genre_artist_header"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/genre_artist_recycler"
|
tools:layout_editor_absoluteX="355dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
tools:src="@drawable/ic_sort_alpha_down" />
|
||||||
app:layout_constraintTop_toBottomOf="@+id/genre_song_count" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/genre_artist_recycler"
|
android:id="@+id/genre_artist_recycler"
|
||||||
|
|
|
@ -13,37 +13,38 @@
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/ui_header_dividers">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/header_text"
|
android:id="@+id/header_title"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="@dimen/padding_medium"
|
||||||
android:fontFamily="@font/inter_semibold"
|
android:fontFamily="@font/inter_semibold"
|
||||||
android:paddingStart="@dimen/padding_medium"
|
android:paddingStart="@dimen/padding_medium"
|
||||||
android:paddingTop="@dimen/padding_small"
|
android:paddingTop="@dimen/padding_small"
|
||||||
android:paddingEnd="@dimen/padding_small"
|
android:paddingEnd="@dimen/padding_small"
|
||||||
android:paddingBottom="@dimen/padding_small"
|
android:paddingBottom="@dimen/padding_small"
|
||||||
android:text="@{header.name}"
|
android:text="@{header.name}"
|
||||||
|
tools:text="Songs"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="19sp"
|
android:textSize="19sp"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/header_button"
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
android:background="@drawable/ui_header_dividers"
|
|
||||||
tools:text="Songs" />
|
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/header_button"
|
android:id="@+id/header_button"
|
||||||
style="@style/Widget.AppCompat.Button.Borderless"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:background="@drawable/ui_header_dividers"
|
android:contentDescription="@string/description_sort_button"
|
||||||
android:tint="?android:attr/colorPrimary"
|
android:paddingStart="@dimen/padding_medium"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
android:paddingTop="@dimen/padding_small"
|
||||||
|
android:background="@drawable/ui_small_unbounded_ripple"
|
||||||
|
android:paddingEnd="@dimen/margin_medium"
|
||||||
|
android:paddingBottom="@dimen/padding_small"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="@+id/header_title"
|
||||||
tools:src="@drawable/ic_clear"
|
tools:src="@drawable/ic_sort_numeric_down" />
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</layout>
|
</layout>
|
|
@ -25,7 +25,6 @@
|
||||||
<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_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_clear_user_queue">Clear queue</string>
|
|
||||||
<string name="label_channel">Music Playback</string>
|
<string name="label_channel">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>
|
||||||
|
|
||||||
|
@ -50,6 +49,7 @@
|
||||||
<string name="description_sort_none">Default Sort Order</string>
|
<string name="description_sort_none">Default Sort Order</string>
|
||||||
<string name="description_sort_alpha_down">Sort from A to Z</string>
|
<string name="description_sort_alpha_down">Sort from A to Z</string>
|
||||||
<string name="description_sort_alpha_up">Sort from Z to A</string>
|
<string name="description_sort_alpha_up">Sort from Z to A</string>
|
||||||
|
<string name="description_clear_user_queue">Clear queue</string>
|
||||||
<string name="description_play">Play</string>
|
<string name="description_play">Play</string>
|
||||||
<string name="description_pause">Pause</string>
|
<string name="description_pause">Pause</string>
|
||||||
<string name="description_skip_next">Skip to next song</string>
|
<string name="description_skip_next">Skip to next song</string>
|
||||||
|
|
Loading…
Reference in a new issue