home: make loading indicator less intrusive

This commit is contained in:
Alexander Capehart 2024-12-28 14:54:20 -07:00
parent 64ce312976
commit 9ccc4cf2ae
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
2 changed files with 43 additions and 140 deletions

View file

@ -20,13 +20,12 @@ package org.oxycblt.auxio.home
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import android.os.SystemClock
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.MenuCompat import androidx.core.view.MenuCompat
import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -313,75 +312,32 @@ class HomeFragment :
} }
private fun updateIndexerState(state: IndexingState?) { private fun updateIndexerState(state: IndexingState?) {
// TODO: Reduce intrusiveness of current loading state:
// 1. "Dry" loads
val binding = requireBinding() val binding = requireBinding()
when (state) { when (state) {
is IndexingState.Completed -> setupCompleteState(binding, state.error) is IndexingState.Completed -> {
is IndexingState.Indexing -> setupIndexingState(binding, state.progress) binding.homeIndexingContainer.isInvisible = state.error == null
null -> { binding.homeIndexingProgress.isInvisible = state.error != null
L.d("Indexer is in indeterminate state") binding.homeIndexingError.isInvisible = state.error == null
binding.homeIndexingContainer.visibility = View.INVISIBLE
} }
} is IndexingState.Indexing -> {
} binding.homeIndexingContainer.isInvisible = false
private fun setupCompleteState(binding: FragmentHomeBinding, error: Exception?) {
if (error == null) {
L.d("Received ok response")
binding.homeIndexingContainer.visibility = View.INVISIBLE
return
}
L.d("Received non-ok response")
val context = requireContext()
binding.homeIndexingContainer.visibility = View.VISIBLE
binding.homeIndexingProgress.visibility = View.INVISIBLE
binding.homeIndexingActions.visibility = View.VISIBLE
L.d("Showing generic error")
binding.homeIndexingStatus.setText(R.string.err_index_failed)
// Configure the action to act as a reload trigger.
binding.homeIndexingTry.apply {
visibility = View.VISIBLE
text = context.getString(R.string.lbl_retry)
setOnClickListener { musicModel.rescan() }
}
binding.homeIndexingMore.apply {
visibility = View.VISIBLE
setOnClickListener {
findNavController().navigateSafe(HomeFragmentDirections.reportError(error))
}
}
}
private fun setupIndexingState(binding: FragmentHomeBinding, progress: IndexingProgress) {
// Remove all content except for the progress indicator.
binding.homeIndexingContainer.visibility = View.VISIBLE
binding.homeIndexingProgress.visibility = View.VISIBLE
binding.homeIndexingActions.visibility = View.INVISIBLE
when (progress) {
is IndexingProgress.Indeterminate -> {
// In a query/initialization state, show a generic loading status.
binding.homeIndexingStatus.text = getString(R.string.lng_indexing)
binding.homeIndexingProgress.isIndeterminate = true
}
is IndexingProgress.Songs -> {
// Actively loading songs, show the current progress.
binding.homeIndexingProgress.apply { binding.homeIndexingProgress.apply {
isInvisible = false
when (state.progress) {
is IndexingProgress.Songs -> {
isIndeterminate = false isIndeterminate = false
max = progress.explored progress = state.progress.loaded
this.progress = progress.loaded max = state.progress.explored
} }
// Avoid aggressively updating the UI for rapid progress updates. is IndexingProgress.Indeterminate -> {
val now = SystemClock.elapsedRealtime() isIndeterminate = true
if (lastUpdateTime > -1 && (now - lastUpdateTime) < 250) {
return
} }
lastUpdateTime = SystemClock.elapsedRealtime() }
binding.homeIndexingStatus.text = }
getString(R.string.fmt_indexing, progress.loaded, progress.explored) binding.homeIndexingError.isInvisible = true
}
null -> {
binding.homeIndexingContainer.isInvisible = true
} }
} }
} }

View file

@ -65,87 +65,34 @@
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
tools:layout="@layout/fragment_home_list" /> tools:layout="@layout/fragment_home_list" />
<org.oxycblt.auxio.home.EdgeFrameLayout
android:id="@+id/home_indexing_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="@dimen/spacing_medium"
android:fitsSystemWindows="true"
android:visibility="invisible">
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:layout_width="match_parent" android:id="@+id/home_indexing_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"> android:layout_gravity="top|start"
android:transitionGroup="true"
android:layout_margin="@dimen/spacing_medium">
<androidx.constraintlayout.widget.ConstraintLayout <com.google.android.material.progressindicator.CircularProgressIndicator
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true">
<TextView
android:id="@+id/home_indexing_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/spacing_medium"
android:gravity="center"
android:text="@string/lng_indexing"
android:textAppearance="@style/TextAppearance.Auxio.BodyLarge"
app:layout_constraintBottom_toTopOf="@+id/home_indexing_actions"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Status" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/home_indexing_progress" android:id="@+id/home_indexing_progress"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_medium" android:layout_margin="@dimen/spacing_tiny" />
android:layout_marginEnd="@dimen/spacing_medium"
android:indeterminate="true"
app:indeterminateAnimationType="disjoint"
app:layout_constraintBottom_toBottomOf="@+id/home_indexing_actions"
app:layout_constraintTop_toTopOf="@+id/home_indexing_actions" />
<LinearLayout <ImageView
android:id="@+id/home_indexing_actions" android:id="@+id/home_indexing_error"
android:layout_width="match_parent" android:layout_width="48dp"
android:layout_height="wrap_content" android:layout_height="48dp"
android:layout_marginStart="@dimen/spacing_medium" android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_medium" android:contentDescription="@string/err_index_failed"
android:layout_marginBottom="@dimen/spacing_medium" android:scaleType="centerInside"
android:orientation="horizontal" android:src="@drawable/ic_feature_request_24"
android:visibility="invisible" app:tint="?attr/colorError"
app:layout_constraintBottom_toBottomOf="parent" tools:visibility="invisible" />
tools:layout_editor_absoluteX="16dp">
<org.oxycblt.auxio.ui.RippleFixMaterialButton
android:id="@+id/home_indexing_try"
style="@style/Widget.Auxio.Button.Primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_small"
android:layout_weight="1"
android:text="@string/lbl_retry" />
<org.oxycblt.auxio.ui.RippleFixMaterialButton
android:id="@+id/home_indexing_more"
style="@style/Widget.Auxio.Button.Secondary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_small"
android:layout_weight="1"
android:text="@string/lbl_show_error_info" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
</org.oxycblt.auxio.home.EdgeFrameLayout>
</FrameLayout> </FrameLayout>