Update LoadingFragment layout
Update the layout of LoadingFragment with a new error icon/text style.
This commit is contained in:
parent
8f850f2288
commit
5e6917f11c
13 changed files with 85 additions and 37 deletions
|
@ -18,6 +18,8 @@ android {
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
dataBinding true
|
dataBinding true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vectorDrawables.useSupportLibrary = true
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
@ -27,10 +29,6 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildFeatures {
|
|
||||||
dataBinding true
|
|
||||||
}
|
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
}
|
}
|
||||||
|
@ -49,7 +47,11 @@ dependencies {
|
||||||
// --- SUPPORT ---
|
// --- SUPPORT ---
|
||||||
implementation 'androidx.core:core-ktx:1.3.1'
|
implementation 'androidx.core:core-ktx:1.3.1'
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||||
|
|
||||||
|
// Permissions
|
||||||
|
implementation 'androidx.activity:activity:1.2.0-alpha08'
|
||||||
|
implementation 'androidx.fragment:fragment:1.3.0-alpha08'
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
def navigation_version = "2.3.0"
|
def navigation_version = "2.3.0"
|
||||||
|
|
|
@ -9,9 +9,15 @@ import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import org.oxycblt.auxio.theme.accent
|
import org.oxycblt.auxio.theme.accent
|
||||||
|
|
||||||
|
const val PERM_READ_EXTERNAL_STORAGE = 2488
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
|
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
|
||||||
|
// Debugging placeholder
|
||||||
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
||||||
|
|
||||||
|
// Apply the theme
|
||||||
setTheme(accent.second)
|
setTheme(accent.second)
|
||||||
|
|
||||||
return super.onCreateView(name, context, attrs)
|
return super.onCreateView(name, context, attrs)
|
||||||
|
@ -19,9 +25,8 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
|
||||||
|
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
Log.d(this::class.simpleName, "Activity Created.")
|
Log.d(this::class.simpleName, "Activity Created.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
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.Observer
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
|
@ -41,14 +40,14 @@ class LoadingFragment : Fragment() {
|
||||||
|
|
||||||
loadingModel.musicRepoResponse.observe(
|
loadingModel.musicRepoResponse.observe(
|
||||||
viewLifecycleOwner,
|
viewLifecycleOwner,
|
||||||
Observer { response ->
|
{ response ->
|
||||||
onMusicLoadResponse(response)
|
onMusicLoadResponse(response)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
loadingModel.doRetry.observe(
|
loadingModel.doRetry.observe(
|
||||||
viewLifecycleOwner,
|
viewLifecycleOwner,
|
||||||
Observer { retry ->
|
{ retry ->
|
||||||
onRetry(retry)
|
onRetry(retry)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -59,7 +58,6 @@ class LoadingFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onMusicLoadResponse(repoResponse: MusicLoaderResponse?) {
|
private fun onMusicLoadResponse(repoResponse: MusicLoaderResponse?) {
|
||||||
|
|
||||||
// Don't run this if the value is null, Which is what the value changes to after
|
// Don't run this if the value is null, Which is what the value changes to after
|
||||||
// this is run.
|
// this is run.
|
||||||
repoResponse?.let { response ->
|
repoResponse?.let { response ->
|
||||||
|
@ -73,13 +71,14 @@ class LoadingFragment : Fragment() {
|
||||||
|
|
||||||
binding.loadingBar.visibility = View.GONE
|
binding.loadingBar.visibility = View.GONE
|
||||||
binding.errorText.visibility = View.VISIBLE
|
binding.errorText.visibility = View.VISIBLE
|
||||||
binding.resetButton.visibility = View.VISIBLE
|
binding.statusIcon.visibility = View.VISIBLE
|
||||||
|
binding.retryButton.visibility = View.VISIBLE
|
||||||
|
|
||||||
if (response == MusicLoaderResponse.NO_MUSIC) {
|
binding.errorText.text =
|
||||||
binding.errorText.text = getString(R.string.error_no_music)
|
if (response == MusicLoaderResponse.NO_MUSIC)
|
||||||
} else {
|
getString(R.string.error_no_music)
|
||||||
binding.errorText.text = getString(R.string.error_music_load_failed)
|
else
|
||||||
}
|
getString(R.string.error_music_load_failed)
|
||||||
}
|
}
|
||||||
|
|
||||||
loadingModel.doneWithResponse()
|
loadingModel.doneWithResponse()
|
||||||
|
@ -90,7 +89,8 @@ class LoadingFragment : Fragment() {
|
||||||
if (retry) {
|
if (retry) {
|
||||||
binding.loadingBar.visibility = View.VISIBLE
|
binding.loadingBar.visibility = View.VISIBLE
|
||||||
binding.errorText.visibility = View.GONE
|
binding.errorText.visibility = View.GONE
|
||||||
binding.resetButton.visibility = View.GONE
|
binding.statusIcon.visibility = View.GONE
|
||||||
|
binding.retryButton.visibility = View.GONE
|
||||||
|
|
||||||
loadingModel.doneWithRetry()
|
loadingModel.doneWithRetry()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.oxycblt.auxio.loading
|
package org.oxycblt.auxio.loading
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.util.Log
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
@ -29,8 +28,6 @@ class LoadingViewModel(private val app: Application) : ViewModel() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
startMusicRepo()
|
startMusicRepo()
|
||||||
|
|
||||||
Log.d(this::class.simpleName, "ViewModel created.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startMusicRepo() {
|
private fun startMusicRepo() {
|
||||||
|
@ -52,9 +49,9 @@ class LoadingViewModel(private val app: Application) : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun retry() {
|
fun retry() {
|
||||||
mDoRetry.value = true
|
|
||||||
|
|
||||||
startMusicRepo()
|
startMusicRepo()
|
||||||
|
|
||||||
|
mDoRetry.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doneWithRetry() {
|
fun doneWithRetry() {
|
||||||
|
|
|
@ -52,7 +52,7 @@ class MusicRepository {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return loader.response
|
return MusicLoaderResponse.NO_MUSIC
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -51,6 +51,10 @@ class MusicLoader(private val resolver: ContentResolver) {
|
||||||
return MusicLoaderResponse.FAILURE
|
return MusicLoaderResponse.FAILURE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (songs.size == 0) {
|
||||||
|
return MusicLoaderResponse.NO_MUSIC
|
||||||
|
}
|
||||||
|
|
||||||
return MusicLoaderResponse.DONE
|
return MusicLoaderResponse.DONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,6 @@ class SongAdapter(private val data: List<Song>) : RecyclerView.Adapter<SongViewH
|
||||||
override fun getItemCount(): Int = data.size
|
override fun getItemCount(): Int = data.size
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder {
|
||||||
val then = System.currentTimeMillis()
|
|
||||||
|
|
||||||
val binding = SongItemBinding.inflate(LayoutInflater.from(parent.context))
|
val binding = SongItemBinding.inflate(LayoutInflater.from(parent.context))
|
||||||
|
|
||||||
// Force the item to *actually* be the screen width so ellipsizing can work.
|
// Force the item to *actually* be the screen width so ellipsizing can work.
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.oxycblt.auxio.recycler.viewholders
|
||||||
|
|
||||||
|
// Generic ClickListener
|
||||||
|
class ClickListener<T>(val action: (T) -> Unit) {
|
||||||
|
fun onClick(action: T) = action
|
||||||
|
}
|
12
app/src/main/res/drawable/ic_error.xml
Normal file
12
app/src/main/res/drawable/ic_error.xml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorPrimary">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M11,15h2v2h-2zM11,7h2v6h-2zM11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z" />
|
||||||
|
</vector>
|
3
app/src/main/res/drawable/ripple.xml
Normal file
3
app/src/main/res/drawable/ripple.xml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:color="?attr/colorPrimary" />
|
|
@ -23,7 +23,7 @@
|
||||||
android:indeterminateTint="?attr/colorPrimary"
|
android:indeterminateTint="?attr/colorPrimary"
|
||||||
android:indeterminateTintMode="src_in"
|
android:indeterminateTintMode="src_in"
|
||||||
android:paddingBottom="@dimen/padding_tiny"
|
android:paddingBottom="@dimen/padding_tiny"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/error_text"
|
app:layout_constraintBottom_toTopOf="@+id/status_icon"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
@ -31,37 +31,54 @@
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
app:layout_constraintVertical_chainStyle="packed"
|
||||||
tools:indeterminateTint="@color/blue" />
|
tools:indeterminateTint="@color/blue" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/status_icon"
|
||||||
|
android:layout_width="@dimen/status_icon_size"
|
||||||
|
android:layout_height="@dimen/status_icon_size"
|
||||||
|
android:indeterminateTint="?attr/colorPrimary"
|
||||||
|
android:indeterminateTintMode="src_in"
|
||||||
|
android:src="@drawable/ic_error"
|
||||||
|
android:contentDescription="@string/description_error_icon"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/error_text"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/loading_bar"
|
||||||
|
app:srcCompat="@drawable/ic_error"
|
||||||
|
tools:tint="@color/blue" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/error_text"
|
android:id="@+id/error_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/inter"
|
android:fontFamily="@font/inter"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/reset_button"
|
android:layout_marginTop="@dimen/margin_small"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/retry_button"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/loading_bar"
|
app:layout_constraintTop_toBottomOf="@+id/status_icon"
|
||||||
tools:text="Some kind of error." />
|
tools:text="Some kind of error." />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/reset_button"
|
android:id="@+id/retry_button"
|
||||||
style="@style/Widget.AppCompat.Button.Borderless.Colored"
|
style="@style/Widget.AppCompat.Button.Borderless.Colored"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/inter_semibold"
|
||||||
android:onClick="@{() -> loadingModel.retry()}"
|
android:onClick="@{() -> loadingModel.retry()}"
|
||||||
android:text="@string/label_retry"
|
android:text="@string/label_retry"
|
||||||
android:visibility="gone"
|
|
||||||
android:fontFamily="@font/inter_semibold"
|
|
||||||
android:textColor="?attr/colorPrimary"
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:visibility="gone"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/error_text"
|
app:layout_constraintTop_toBottomOf="@+id/error_text"
|
||||||
tools:visibility="visible"
|
app:layout_constraintVertical_bias="0.673"
|
||||||
tools:textColor="@color/blue" />
|
tools:textColor="@color/blue"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</layout>
|
</layout>
|
|
@ -7,10 +7,12 @@
|
||||||
<dimen name="margin_small">8dp</dimen>
|
<dimen name="margin_small">8dp</dimen>
|
||||||
<dimen name="margin_medium">16dp</dimen>
|
<dimen name="margin_medium">16dp</dimen>
|
||||||
|
|
||||||
<dimen name="cover_size_compact">44dp</dimen>
|
<dimen name="status_icon_size">48dp</dimen>
|
||||||
<dimen name="cover_size_normal">56dp</dimen>
|
|
||||||
|
|
||||||
<dimen name="tab_menu_size">40dp</dimen>
|
<dimen name="tab_menu_size">40dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="cover_size_compact">44dp</dimen>
|
||||||
|
<dimen name="cover_size_normal">56dp</dimen>
|
||||||
|
|
||||||
<dimen name="elevation_normal">4dp</dimen>
|
<dimen name="elevation_normal">4dp</dimen>
|
||||||
</resources>
|
</resources>
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
<string name="error_no_music">No music found.</string>
|
<string name="error_no_music">No music found.</string>
|
||||||
<string name="error_music_load_failed">Music loading failed.</string>
|
<string name="error_music_load_failed">Music loading failed.</string>
|
||||||
|
<string name="error_no_perms">Auxio needs to be allowed to read your music library.</string>
|
||||||
|
|
||||||
<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>
|
||||||
|
@ -18,4 +19,5 @@
|
||||||
<string name="format_song_info">%s / %s</string>
|
<string name="format_song_info">%s / %s</string>
|
||||||
|
|
||||||
<string name="description_cover_art">Cover art for </string>
|
<string name="description_cover_art">Cover art for </string>
|
||||||
|
<string name="description_error_icon">Error Icon</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue