Update semantics slightly
Change some naming/structure somewhat, and move all TODOs from AuxioTODO to the project itself.
This commit is contained in:
parent
a72cb48c71
commit
59c087d653
32 changed files with 126 additions and 126 deletions
41
AuxioTODO
41
AuxioTODO
|
@ -1,41 +0,0 @@
|
|||
TODO:
|
||||
|
||||
TODOs surrounded with ?s are things I want to do, but need to do more research on and may be a nightmare to implement.
|
||||
TODOs surrounded with !s are things I tried to do, but failed for reasons included in the TODO. I still want to add these, but theres no way for me to do them at the moment.
|
||||
|
||||
/detail/
|
||||
|
||||
- ? Implement Toolbar update functionality ?
|
||||
- ! Implement shared element transitions [Return transitions are broken] !
|
||||
|
||||
/music/
|
||||
|
||||
- Add option to show all genres
|
||||
- ! Move genres to songs [Wont find songs w/o genres]!
|
||||
- ! Remove lists from music models [Current genre loading system makes it impossible] !
|
||||
- ! Dont determine track/album/artist counts on the fly [Audio columns for those values are broken] !
|
||||
|
||||
/songs/
|
||||
|
||||
- Search when LibraryFragment isnt enabled
|
||||
- ? Sorting ?
|
||||
- ? Fast Scrolling ?
|
||||
|
||||
/library/
|
||||
|
||||
- Exit functionality
|
||||
- ? Add icons to overflow menu items ?
|
||||
- ? Add Nested Nav to Library ViewPager fragment [Hold fire on this until everything else is added, there could be sneaky bugs later on if you add it now] ?
|
||||
- ! Move Adapter functionality to ListAdapter [RecyclerView scrolls to middle/bottom when data is re-sorted] !
|
||||
|
||||
/playback/
|
||||
-
|
||||
|
||||
/other/
|
||||
- Highlight recycler items when they are being played
|
||||
|
||||
/bugs/
|
||||
- Fix issue where fast navigations will cause the app to not display anything
|
||||
|
||||
To be added:
|
||||
/prefs/
|
|
@ -7,6 +7,9 @@ import android.view.View
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import org.oxycblt.auxio.theme.accent
|
||||
|
||||
// FIXME: Fix bug where fast navigation will break the fade animation and
|
||||
// lead to nothing being displayed [Possibly Un-fixable]
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
|
||||
|
|
|
@ -57,6 +57,8 @@ class MainFragment : Fragment() {
|
|||
|
||||
// --- UI SETUP ---
|
||||
|
||||
// TODO: Add nested viewpager navigation [If practical]
|
||||
|
||||
binding.lifecycleOwner = this
|
||||
binding.mainViewPager.adapter = PagerAdapter()
|
||||
|
||||
|
@ -70,6 +72,8 @@ class MainFragment : Fragment() {
|
|||
}
|
||||
}.attach()
|
||||
|
||||
binding.compactPlayback.visibility = View.GONE
|
||||
|
||||
// Set up the selected/deselected colors
|
||||
binding.mainTabs.addOnTabSelectedListener(
|
||||
object : TabLayout.OnTabSelectedListener {
|
||||
|
|
|
@ -16,6 +16,9 @@ import org.oxycblt.auxio.recycler.ClickListener
|
|||
import org.oxycblt.auxio.theme.applyDivider
|
||||
import org.oxycblt.auxio.theme.disable
|
||||
|
||||
// TODO: Add media controls to DetailFragments [Play, Shuffle]
|
||||
// TODO: Implement a system where if the main info [Name, Parent, Counts] scrolls off of
|
||||
// the screen, then update the toolbar to show that info w/the media controls
|
||||
class ArtistDetailFragment : Fragment() {
|
||||
|
||||
private val args: ArtistDetailFragmentArgs by navArgs()
|
||||
|
|
|
@ -8,6 +8,11 @@ import org.oxycblt.auxio.music.Artist
|
|||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
|
||||
// ViewModel for the Detail Fragments.
|
||||
// TODO:
|
||||
// - Implement a system where the Toolbar will update with the info [And Media Controls] when
|
||||
// the main info of the detail fragment is removed.
|
||||
// - Implement shared element transitions [If that is even possible]
|
||||
class DetailViewModel : ViewModel() {
|
||||
private var mIsNavigating = false
|
||||
val isNavigating: Boolean get() = mIsNavigating
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.oxycblt.auxio.theme.applyColor
|
|||
import org.oxycblt.auxio.theme.applyDivider
|
||||
import org.oxycblt.auxio.theme.resolveAttr
|
||||
|
||||
// A Fragment to show all the music in the Library.
|
||||
class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
||||
|
||||
private val musicModel: MusicViewModel by activityViewModels {
|
||||
|
@ -57,6 +58,7 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
|||
|
||||
// --- UI SETUP ---
|
||||
|
||||
// TODO: Add exit functionality
|
||||
binding.libraryToolbar.apply {
|
||||
overflowIcon = ContextCompat.getDrawable(
|
||||
requireContext(), R.drawable.ic_sort_none
|
||||
|
@ -78,6 +80,7 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
|||
true
|
||||
}
|
||||
|
||||
// TODO: Add icons to overflow menu items
|
||||
menu.apply {
|
||||
val item = findItem(R.id.action_search)
|
||||
val searchView = item.actionView as SearchView
|
||||
|
@ -115,6 +118,8 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Change LibraryAdapter to a ListAdapter
|
||||
// [If there's a way to preserve scroll position properly]
|
||||
binding.libraryRecycler.apply {
|
||||
adapter = libraryAdapter
|
||||
|
||||
|
@ -176,8 +181,10 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
|||
}
|
||||
|
||||
private fun navToItem(baseModel: BaseModel) {
|
||||
// TODO: Implement shared element transitions to the DetailFragments [If possible]
|
||||
|
||||
// If the item is a song [That was selected through search], then update the playback
|
||||
// to that song instead of doing any naviagation
|
||||
// to that song instead of doing any navigation
|
||||
if (baseModel is Song) {
|
||||
playbackModel.updateSong(baseModel)
|
||||
return
|
||||
|
|
|
@ -7,7 +7,6 @@ import android.util.Log
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -38,7 +37,7 @@ class LoadingFragment : Fragment(R.layout.fragment_loading) {
|
|||
) { granted: Boolean ->
|
||||
// If its actually granted, restart the loading process again.
|
||||
if (granted) {
|
||||
wipeViews(binding)
|
||||
returnToLoading(binding)
|
||||
|
||||
musicModel.reload()
|
||||
}
|
||||
|
@ -51,13 +50,45 @@ class LoadingFragment : Fragment(R.layout.fragment_loading) {
|
|||
|
||||
// --- VIEWMODEL SETUP ---
|
||||
|
||||
musicModel.response.observe(viewLifecycleOwner) { onMusicLoadResponse(it, binding) }
|
||||
musicModel.doReload.observe(viewLifecycleOwner) { onRetry(it, binding) }
|
||||
musicModel.doGrant.observe(viewLifecycleOwner) { onGrant(it, permLauncher) }
|
||||
musicModel.response.observe(viewLifecycleOwner) {
|
||||
if (it == MusicLoaderResponse.DONE) {
|
||||
findNavController().navigate(
|
||||
LoadingFragmentDirections.actionToMain()
|
||||
)
|
||||
} else {
|
||||
binding.loadingErrorText.text =
|
||||
if (it == MusicLoaderResponse.NO_MUSIC)
|
||||
getString(R.string.error_no_music)
|
||||
else
|
||||
getString(R.string.error_music_load_failed)
|
||||
|
||||
// If the response wasn't a success, then show the specific error message
|
||||
// depending on which error response was given, along with a retry button
|
||||
showError(binding)
|
||||
binding.loadingRetryButton.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
musicModel.doReload.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
returnToLoading(binding)
|
||||
musicModel.doneWithReload()
|
||||
}
|
||||
}
|
||||
|
||||
musicModel.doGrant.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
permLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
musicModel.doneWithGrant()
|
||||
}
|
||||
}
|
||||
|
||||
// Force an error screen if the permissions are denied or the prompt needs to be shown.
|
||||
if (checkPerms()) {
|
||||
onNoPerms(binding)
|
||||
showError(binding)
|
||||
|
||||
binding.loadingGrantButton.visibility = View.VISIBLE
|
||||
binding.loadingErrorText.text = getString(R.string.error_no_perms)
|
||||
} else {
|
||||
musicModel.go()
|
||||
}
|
||||
|
@ -78,61 +109,15 @@ class LoadingFragment : Fragment(R.layout.fragment_loading) {
|
|||
) == PackageManager.PERMISSION_DENIED
|
||||
}
|
||||
|
||||
private fun onMusicLoadResponse(
|
||||
response: MusicLoaderResponse?,
|
||||
binding: FragmentLoadingBinding
|
||||
) {
|
||||
if (response == MusicLoaderResponse.DONE) {
|
||||
findNavController().navigate(
|
||||
LoadingFragmentDirections.actionToMain()
|
||||
)
|
||||
} else {
|
||||
binding.loadingErrorText.text =
|
||||
if (response == MusicLoaderResponse.NO_MUSIC)
|
||||
getString(R.string.error_no_music)
|
||||
else
|
||||
getString(R.string.error_music_load_failed)
|
||||
|
||||
// If the response wasn't a success, then show the specific error message
|
||||
// depending on which error response was given, along with a retry button
|
||||
binding.loadingBar.visibility = View.GONE
|
||||
binding.loadingErrorText.visibility = View.VISIBLE
|
||||
binding.loadingErrorIcon.visibility = View.VISIBLE
|
||||
binding.loadingRetryButton.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
private fun onNoPerms(binding: FragmentLoadingBinding) {
|
||||
// If there are no perms, switch out the view elements as if an error screen was being
|
||||
// shown, but show the label that Auxio needs to read external storage to function,
|
||||
// along with a GRANT button
|
||||
|
||||
// Remove the loading indicator and show the error groups
|
||||
private fun showError(binding: FragmentLoadingBinding) {
|
||||
binding.loadingBar.visibility = View.GONE
|
||||
binding.loadingErrorIcon.visibility = View.VISIBLE
|
||||
binding.loadingGrantButton.visibility = View.VISIBLE
|
||||
binding.loadingErrorText.visibility = View.VISIBLE
|
||||
|
||||
binding.loadingErrorText.text = getString(R.string.error_no_perms)
|
||||
}
|
||||
|
||||
private fun onRetry(retry: Boolean, binding: FragmentLoadingBinding) {
|
||||
if (retry) {
|
||||
wipeViews(binding)
|
||||
|
||||
musicModel.doneWithReload()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onGrant(grant: Boolean, permLauncher: ActivityResultLauncher<String>) {
|
||||
if (grant) {
|
||||
permLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
|
||||
musicModel.doneWithGrant()
|
||||
}
|
||||
}
|
||||
|
||||
// Wipe views and switch back to the plain ProgressBar
|
||||
private fun wipeViews(binding: FragmentLoadingBinding) {
|
||||
private fun returnToLoading(binding: FragmentLoadingBinding) {
|
||||
binding.loadingBar.visibility = View.VISIBLE
|
||||
binding.loadingErrorText.visibility = View.GONE
|
||||
binding.loadingErrorIcon.visibility = View.GONE
|
||||
|
|
|
@ -2,6 +2,10 @@ package org.oxycblt.auxio.music
|
|||
|
||||
import android.net.Uri
|
||||
|
||||
// --- MUSIC MODELS ---
|
||||
// TODO: Remove parent/child references so that they can be parcelable [Would require genre rework]
|
||||
// TODO: Dont determine artist/album/song counts on the fly [If possible]
|
||||
|
||||
// The base model for all music
|
||||
// This is used in a lot of general functions in order to cut down on code
|
||||
sealed class BaseModel {
|
||||
|
|
|
@ -17,9 +17,7 @@ import org.oxycblt.auxio.music.processing.MusicLoaderResponse
|
|||
import org.oxycblt.auxio.music.processing.MusicSorter
|
||||
|
||||
// ViewModel for music storage.
|
||||
// FIXME: This system can be improved in multiple ways
|
||||
// - Remove lists/parents from models so that they can be parcelable
|
||||
// - Move genre usage to songs [If there's a way to find songs without a genre]
|
||||
// TODO: Move genre usage to songs [If there's a way to find songs without a genre]
|
||||
class MusicViewModel(private val app: Application) : ViewModel() {
|
||||
|
||||
// Coroutine
|
||||
|
|
|
@ -21,6 +21,8 @@ import java.io.InputStream
|
|||
const val MOSAIC_BITMAP_SIZE = 512
|
||||
const val MOSAIC_BITMAP_INCREMENT = 256
|
||||
|
||||
// A Fetcher that takes multiple cover uris and turns them into a 2x2 mosaic image.
|
||||
// TODO: Add 4x4 mosaics?
|
||||
class MosaicFetcher(private val context: Context) : Fetcher<List<Uri>> {
|
||||
override suspend fun fetch(
|
||||
pool: BitmapPool,
|
||||
|
@ -30,8 +32,9 @@ class MosaicFetcher(private val context: Context) : Fetcher<List<Uri>> {
|
|||
): FetchResult {
|
||||
val streams = mutableListOf<InputStream>()
|
||||
|
||||
for (uri in data) {
|
||||
val stream: InputStream? = context.contentResolver.openInputStream(uri)
|
||||
// Load the streams.
|
||||
data.forEach {
|
||||
val stream: InputStream? = context.contentResolver.openInputStream(it)
|
||||
|
||||
if (stream != null) {
|
||||
streams.add(stream)
|
||||
|
@ -39,7 +42,7 @@ class MosaicFetcher(private val context: Context) : Fetcher<List<Uri>> {
|
|||
}
|
||||
|
||||
// If so many streams failed that there's not enough images to make a mosaic, then
|
||||
// just return the first album.
|
||||
// just return the first cover image.
|
||||
if (streams.size < 4) {
|
||||
streams.forEach { it.close() }
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ enum class MusicLoaderResponse {
|
|||
}
|
||||
|
||||
// Class that loads music from the FileSystem.
|
||||
// TODO: Add custom artist images from the filesystem
|
||||
class MusicLoader(
|
||||
private val resolver: ContentResolver,
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ class CompactPlaybackFragment : Fragment() {
|
|||
): View? {
|
||||
val binding = FragmentCompactPlaybackBinding.inflate(inflater)
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.lifecycleOwner = this
|
||||
|
||||
// Put a placeholder song in the binding & hide the playback fragment initially,
|
||||
|
@ -31,6 +33,9 @@ class CompactPlaybackFragment : Fragment() {
|
|||
binding.song = musicModel.songs.value!![0]
|
||||
binding.root.visibility = View.GONE
|
||||
|
||||
// --- VIEWMODEL SETUP ---
|
||||
|
||||
// TODO: Add some kind of animation to when this view becomes visible/invisible.
|
||||
playbackModel.currentSong.observe(viewLifecycleOwner) {
|
||||
if (it == null) {
|
||||
Log.d(this::class.simpleName, "Hiding playback bar due to no song being played.")
|
||||
|
|
|
@ -15,7 +15,9 @@ import org.oxycblt.auxio.music.Song
|
|||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
|
||||
// Shared ViewHolders for each ViewModel, providing basic information
|
||||
// All new instances should be created with from(context, listener) instead of direct instantiation.
|
||||
// All new instances should be created with from() instead of direct instantiation.
|
||||
// TODO: Add indicators to song recycler items when they're being played.
|
||||
|
||||
class GenreViewHolder private constructor(
|
||||
listener: ClickListener<Genre>,
|
||||
private val binding: ItemGenreBinding
|
||||
|
@ -82,6 +84,8 @@ class AlbumViewHolder private constructor(
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Add indicators to song recycler items when they're being played.
|
||||
|
||||
class SongViewHolder private constructor(
|
||||
listener: ClickListener<Song>,
|
||||
private val binding: ItemSongBinding
|
||||
|
|
|
@ -12,7 +12,6 @@ import org.oxycblt.auxio.music.MusicViewModel
|
|||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
import org.oxycblt.auxio.theme.applyDivider
|
||||
|
||||
class SongsFragment : Fragment() {
|
||||
private val musicModel: MusicViewModel by activityViewModels {
|
||||
MusicViewModel.Factory(requireActivity().application)
|
||||
|
@ -27,6 +26,9 @@ class SongsFragment : Fragment() {
|
|||
): View? {
|
||||
val binding = FragmentSongsBinding.inflate(inflater)
|
||||
|
||||
// TODO: Add option to search songs if LibraryFragment isn't enabled
|
||||
// TODO: Maybe add fast scrolling or sorting
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.songRecycler.apply {
|
||||
|
|
|
@ -5,5 +5,7 @@
|
|||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
app:defaultNavHost="true"
|
||||
app:navGraph="@navigation/nav_main"
|
||||
tools:context=".MainActivity"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" />
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" />
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".detail.AlbumDetailFragment">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".detail.ArtistDetailFragment">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -67,12 +67,12 @@
|
|||
android:singleLine="true"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
|
||||
android:text="@{@string/format_info(song.album.name, song.album.artist.name)}"
|
||||
android:text="@{@string/format_info(song.album.artist.name, song.album.name)}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/song_name"
|
||||
tools:text="Artist / Album" />
|
||||
tools:text="Artist Name / Album Name" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".detail.GenreDetailFragment">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".library.LibraryFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
tools:context=".loading.LoadingFragment">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".MainFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -16,7 +17,7 @@
|
|||
android:layout_weight="1" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/playback_bar"
|
||||
android:id="@+id/compact_playback"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:name="org.oxycblt.auxio.playback.CompactPlaybackFragment"
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".songs.SongsFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".recycler.viewholders.AlbumViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
@ -58,6 +59,6 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/album_name"
|
||||
tools:text="10 Songs" />
|
||||
tools:text="Artist / 10 Songs" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".detail.adapters.DetailSongAdapter.ViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".recycler.viewholders.ArtistViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".detail.adapters.DetailAlbumAdapter.ViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".recycler.viewholders.GenreViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".detail.adapters.DetailArtistAdapter.ViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:context=".recycler.viewholders.HeaderViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".recycler.viewholders.SongViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<dimen name="cover_size_compact">44dp</dimen>
|
||||
<dimen name="cover_size_normal">56dp</dimen>
|
||||
<dimen name="cover_size_large">68dp</dimen>
|
||||
<dimen name="cover_size_huge">230dp</dimen>
|
||||
<dimen name="cover_size_huge">250dp</dimen>
|
||||
|
||||
<dimen name="track_number_width">32dp</dimen>
|
||||
<dimen name="track_number_text_size_max">20sp</dimen>
|
||||
|
|
Loading…
Reference in a new issue