Add proper placeholders
Add placeholders for album art, artist name, and album name if there arent any from the file itself.
This commit is contained in:
parent
16038567dd
commit
d158fc5786
10 changed files with 37 additions and 38 deletions
|
@ -3,6 +3,7 @@ package org.oxycblt.auxio
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
@ -10,7 +11,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
// AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
||||||
|
|
||||||
Log.d(this::class.simpleName, "Activity Created.")
|
Log.d(this::class.simpleName, "Activity Created.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,6 @@ import android.view.ViewGroup
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentLibraryBinding
|
import org.oxycblt.auxio.databinding.FragmentLibraryBinding
|
||||||
import org.oxycblt.auxio.recycler.adapters.AlbumAdapter
|
import org.oxycblt.auxio.recycler.adapters.AlbumAdapter
|
||||||
|
@ -23,11 +19,6 @@ class LibraryFragment : Fragment() {
|
||||||
ViewModelProvider(this).get(LibraryViewModel::class.java)
|
ViewModelProvider(this).get(LibraryViewModel::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val inflateJob = Job()
|
|
||||||
private val mainScope = CoroutineScope(
|
|
||||||
inflateJob + Dispatchers.Main
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
@ -37,14 +28,7 @@ class LibraryFragment : Fragment() {
|
||||||
inflater, R.layout.fragment_library, container, false
|
inflater, R.layout.fragment_library, container, false
|
||||||
)
|
)
|
||||||
|
|
||||||
// Offload the initial layout creation to a coroutine so that it doesn't hold up
|
|
||||||
// the UI thread. Hacky but it results in a smoother experience.
|
|
||||||
mainScope.launch {
|
|
||||||
binding.libraryRecycler.adapter = AlbumAdapter(libraryModel.albums.value!!)
|
binding.libraryRecycler.adapter = AlbumAdapter(libraryModel.albums.value!!)
|
||||||
binding.libraryRecycler.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
// binding.libraryRecycler.adapter = adapter
|
|
||||||
binding.libraryRecycler.applyDivider()
|
binding.libraryRecycler.applyDivider()
|
||||||
binding.libraryRecycler.setHasFixedSize(true)
|
binding.libraryRecycler.setHasFixedSize(true)
|
||||||
|
|
||||||
|
@ -52,10 +36,4 @@ class LibraryFragment : Fragment() {
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
|
|
||||||
inflateJob.cancel()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ class MusicRepository {
|
||||||
|
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
|
|
||||||
val loader = MusicLoader(app)
|
val loader = MusicLoader(app.contentResolver)
|
||||||
|
|
||||||
if (loader.response == MusicLoaderResponse.DONE) {
|
if (loader.response == MusicLoaderResponse.DONE) {
|
||||||
// If the loading succeeds, then process the songs and set them.
|
// If the loading succeeds, then process the songs and set them.
|
||||||
|
|
|
@ -79,7 +79,7 @@ fun ImageView.getCoverArt(any: Any) {
|
||||||
load(uri) {
|
load(uri) {
|
||||||
crossfade(true)
|
crossfade(true)
|
||||||
placeholder(android.R.color.transparent)
|
placeholder(android.R.color.transparent)
|
||||||
error(android.R.color.transparent)
|
error(R.drawable.music_icon)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,3 +92,19 @@ fun TextView.getAlbumSongs(album: Album) {
|
||||||
context.getString(R.string.format_multi_song_count, album.numSongs.toString())
|
context.getString(R.string.format_multi_song_count, album.numSongs.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BindingAdapter("songInfo")
|
||||||
|
fun TextView.getSongInfo(song: Song) {
|
||||||
|
var artist = song.album.artist.name
|
||||||
|
var album = song.album.title
|
||||||
|
|
||||||
|
if (artist == "") {
|
||||||
|
artist = context.getString(R.string.label_unknown_artist)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (album == "") {
|
||||||
|
album = context.getString(R.string.label_unknown_album)
|
||||||
|
}
|
||||||
|
|
||||||
|
text = context.getString(R.string.format_song_info, artist, album)
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.oxycblt.auxio.music.processing
|
package org.oxycblt.auxio.music.processing
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.provider.MediaStore.Audio.Albums
|
import android.provider.MediaStore.Audio.Albums
|
||||||
|
@ -21,7 +20,7 @@ enum class MusicLoaderResponse {
|
||||||
|
|
||||||
// Class that loads music from the FileSystem.
|
// Class that loads music from the FileSystem.
|
||||||
// FIXME: This thing probably has some memory leaks *somewhere*
|
// FIXME: This thing probably has some memory leaks *somewhere*
|
||||||
class MusicLoader(app: Application) {
|
class MusicLoader(private val resolver: ContentResolver) {
|
||||||
|
|
||||||
var genres = mutableListOf<Genre>()
|
var genres = mutableListOf<Genre>()
|
||||||
var artists = mutableListOf<Artist>()
|
var artists = mutableListOf<Artist>()
|
||||||
|
@ -34,7 +33,6 @@ class MusicLoader(app: Application) {
|
||||||
private var songCursor: Cursor? = null
|
private var songCursor: Cursor? = null
|
||||||
|
|
||||||
val response: MusicLoaderResponse
|
val response: MusicLoaderResponse
|
||||||
private val resolver: ContentResolver = app.contentResolver
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
response = findMusic()
|
response = findMusic()
|
||||||
|
|
|
@ -8,9 +8,6 @@ import android.view.ViewGroup
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentSongsBinding
|
import org.oxycblt.auxio.databinding.FragmentSongsBinding
|
||||||
import org.oxycblt.auxio.recycler.adapters.SongAdapter
|
import org.oxycblt.auxio.recycler.adapters.SongAdapter
|
||||||
|
@ -18,11 +15,6 @@ import org.oxycblt.auxio.recycler.applyDivider
|
||||||
|
|
||||||
class SongsFragment : Fragment() {
|
class SongsFragment : Fragment() {
|
||||||
|
|
||||||
private val inflateJob = Job()
|
|
||||||
private val mainScope = CoroutineScope(
|
|
||||||
inflateJob + Dispatchers.Main
|
|
||||||
)
|
|
||||||
|
|
||||||
private val songsModel: SongsViewModel by lazy {
|
private val songsModel: SongsViewModel by lazy {
|
||||||
ViewModelProvider(this).get(SongsViewModel::class.java)
|
ViewModelProvider(this).get(SongsViewModel::class.java)
|
||||||
}
|
}
|
||||||
|
|
10
app/src/main/res/drawable/music_icon.xml
Normal file
10
app/src/main/res/drawable/music_icon.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?android:attr/colorPrimary">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,3v10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55 -2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4V7h4V3h-6z" />
|
||||||
|
</vector>
|
|
@ -50,9 +50,9 @@
|
||||||
android:layout_marginStart="@dimen/margin_medium"
|
android:layout_marginStart="@dimen/margin_medium"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:text="@{@string/format_song_info(song.album.artist.name, song.album.title)}"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
app:songInfo="@{song}"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/duration"
|
app:layout_constraintEnd_toStartOf="@+id/duration"
|
||||||
app:layout_constraintStart_toEndOf="@+id/cover"
|
app:layout_constraintStart_toEndOf="@+id/cover"
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
|
|
||||||
<string name="label_retry">Retry</string>
|
<string name="label_retry">Retry</string>
|
||||||
<string name="label_single_song">1 Song</string>
|
<string name="label_single_song">1 Song</string>
|
||||||
|
<string name="label_unknown_genre">Unknown Genre</string>
|
||||||
|
<string name="label_unknown_artist">Unknown Artist</string>
|
||||||
|
<string name="label_unknown_album">Unknown Album</string>
|
||||||
|
|
||||||
<string name="format_multi_song_count">%s Songs</string>
|
<string name="format_multi_song_count">%s Songs</string>
|
||||||
<string name="format_song_info">%s / %s</string>
|
<string name="format_song_info">%s / %s</string>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Base theme -->
|
<!-- Base theme -->
|
||||||
<style name="BaseTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
<style name="BaseTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||||
|
<item name="android:colorPrimary">@color/blue</item>
|
||||||
<item name="android:windowBackground">@color/background</item>
|
<item name="android:windowBackground">@color/background</item>
|
||||||
<item name="android:statusBarColor">@android:color/black</item>
|
<item name="android:statusBarColor">@android:color/black</item>
|
||||||
<item name="android:fontFamily">@font/inter</item>
|
<item name="android:fontFamily">@font/inter</item>
|
||||||
|
|
Loading…
Reference in a new issue