loading: improve new ui

Improve the loading UI somewhat, reverting the progress bar and
applying some padding to the icon so that it looks a bit better
on Android 12.
This commit is contained in:
OxygenCobalt 2021-08-09 19:42:01 -06:00
parent fe29e01311
commit a5f65d39a5
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
8 changed files with 65 additions and 65 deletions

View file

@ -54,10 +54,7 @@ class LibraryFragment : Fragment() {
savedInstanceState: Bundle?
): View {
val binding = FragmentLibraryBinding.inflate(inflater)
val libraryAdapter = LibraryAdapter(::navToDetail) { view, data ->
newMenu(view, data)
}
val libraryAdapter = LibraryAdapter(::navToDetail, ::newMenu)
// --- UI SETUP ---

View file

@ -33,6 +33,7 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentLoadingBinding
import org.oxycblt.auxio.logD
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.ui.isLandscape
/**
* Fragment that handles what to display during the loading process.
@ -58,6 +59,10 @@ class LoadingFragment : Fragment() {
binding.lifecycleOwner = viewLifecycleOwner
binding.loadingModel = loadingModel
// The loading panel shouldn't fit the system window on landscape as that will cause it
// to be mis-aligned with the Auxio icon.
binding.loadingPanel.fitsSystemWindows = !isLandscape(resources)
// --- VIEWMODEL SETUP ---
loadingModel.doGrant.observe(viewLifecycleOwner) { doGrant ->
@ -141,7 +146,6 @@ class LoadingFragment : Fragment() {
*/
private fun showLoading(binding: FragmentLoadingBinding) {
binding.apply {
loadingErrorIcon.visibility = View.INVISIBLE
loadingErrorText.visibility = View.INVISIBLE
loadingActionButton.visibility = View.INVISIBLE
loadingCircle.visibility = View.VISIBLE
@ -155,7 +159,6 @@ class LoadingFragment : Fragment() {
*/
private fun showError(binding: FragmentLoadingBinding, error: MusicStore.Response) {
binding.loadingCircle.visibility = View.GONE
binding.loadingErrorIcon.visibility = View.VISIBLE
binding.loadingErrorText.visibility = View.VISIBLE
binding.loadingActionButton.visibility = View.VISIBLE

View file

@ -32,16 +32,34 @@ sealed class BaseModel {
abstract val name: String
}
/**
* Provides a versatile static hash for a music item that will not change when
* MediaStore changes.
*
* The reason why this is used is down a couple of reasons:
* - MediaStore will refresh the unique ID of a piece of media whenever the library
* changes, which creates bad UX
* - Using song names makes collisions too common to be reliable
* - Hashing into an integer makes databases both smaller and more efficent
*
* This does lock me into a "Load everything at once, lol" architecture for Auxio, but I
* think its worth it.
*
* @property hash A unique-ish hash for this media item
*
* TODO: Make this hash stronger
*/
sealed interface Hashable {
val hash: Int
}
/**
* [BaseModel] variant that denotes that this object is a parent of other data objects, such
* as an [Album] or [Artist]
* @property hash A versatile, unique(ish) hash used for databases
* @property displayName Name that handles the usage of [Genre.resolvedName]
* and the normal [BaseModel.name]
*/
sealed class Parent : BaseModel() {
abstract val hash: Int
sealed class Parent : BaseModel(), Hashable {
val displayName: String get() = if (this is Genre) {
resolvedName
} else {
@ -61,7 +79,6 @@ sealed class Parent : BaseModel() {
* These are not ensured to be linked due to possible quirks in the genre loading system.
* @property seconds The Song's duration in seconds
* @property formattedDuration The Song's duration as a duration string.
* @property hash A versatile, unique(ish) hash used for databases
*/
data class Song(
override val id: Long,
@ -70,7 +87,7 @@ data class Song(
val albumId: Long,
val track: Int,
val duration: Long
) : BaseModel() {
) : BaseModel(), Hashable {
private var mAlbum: Album? = null
private var mGenre: Genre? = null
@ -80,7 +97,12 @@ data class Song(
val seconds = duration / 1000
val formattedDuration = seconds.toDuration()
val hash = songHash()
override val hash: Int get() {
var result = name.hashCode()
result = 31 * result + track
result = 31 * result + duration.hashCode()
return result
}
fun linkAlbum(album: Album) {
if (mAlbum == null) {
@ -93,13 +115,6 @@ data class Song(
mGenre = genre
}
}
private fun songHash(): Int {
var result = name.hashCode()
result = 31 * result + track
result = 31 * result + duration.hashCode()
return result
}
}
/**
@ -127,7 +142,12 @@ data class Album(
val totalDuration: String get() =
songs.sumOf { it.seconds }.toDuration()
override val hash = albumHash()
override val hash: Int get() {
var result = name.hashCode()
result = 31 * result + artistName.hashCode()
result = 31 * result + year
return result
}
fun linkArtist(artist: Artist) {
mArtist = artist
@ -139,13 +159,6 @@ data class Album(
mSongs.add(song)
}
}
private fun albumHash(): Int {
var result = name.hashCode()
result = 31 * result + artistName.hashCode()
result = 31 * result + year
return result
}
}
/**

View file

@ -60,9 +60,7 @@ class SearchFragment : Fragment() {
): View {
val binding = FragmentSearchBinding.inflate(inflater)
val searchAdapter = SearchAdapter(::onItemSelection) { view, data ->
newMenu(view, data)
}
val searchAdapter = SearchAdapter(::onItemSelection, ::newMenu)
val toolbarParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams
val defaultParams = toolbarParams.scrollFlags

View file

@ -49,9 +49,7 @@ class SongsFragment : Fragment() {
savedInstanceState: Bundle?
): View {
val binding = FragmentSongsBinding.inflate(inflater)
val songAdapter = SongsAdapter(musicStore.songs, playbackModel::playSong) { view, data ->
newMenu(view, data)
}
val songAdapter = SongsAdapter(musicStore.songs, playbackModel::playSong, ::newMenu)
// --- UI SETUP ---

View file

@ -16,73 +16,61 @@
android:gravity="center"
android:orientation="vertical">
<!-- TODO: Get this splash icon working with Android 12 splashes -->
<!--
TODO: Get this to line up with Android 12's splash screen when I can figure
out what they do
-->
<ImageView
android:id="@+id/loading_splash"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/desc_auxio_icon"
android:scaleType="fitCenter"
android:padding="@dimen/spacing_huge"
android:src="@drawable/ic_launcher_foreground" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:id="@+id/loading_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/spacing_large"
android:animateLayoutChanges="true"
android:layout_gravity="bottom"
android:fitsSystemWindows="true"
android:gravity="center"
android:orientation="vertical">
<com.google.android.material.progressindicator.LinearProgressIndicator
<ProgressBar
android:id="@+id/loading_circle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
app:layout_constraintBottom_toBottomOf="@+id/loading_action_button"
app:layout_constraintTop_toTopOf="@+id/loading_error_icon" />
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/loading_error_text"
android:fontFamily="@font/inter_semibold"
android:textSize="@dimen/text_size_mid_large"
android:textColor="?android:attr/textColorPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/spacing_small"
android:fontFamily="@font/inter_semibold"
android:textAlignment="center"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/text_size_mid_large"
android:visibility="invisible"
app:layout_constraintBottom_toTopOf="@+id/loading_action_button"
tools:text="No Music Found" />
<ImageView
android:id="@+id/loading_error_icon"
android:layout_width="@dimen/size_error_icon"
android:layout_height="@dimen/size_error_icon"
android:layout_marginBottom="@dimen/spacing_small"
android:contentDescription="@string/desc_error"
android:src="@drawable/ic_error"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/loading_error_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible" />
<com.google.android.material.button.MaterialButton
android:id="@+id/loading_action_button"
style="@style/Widget.Button.Vibrant.Primary"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_mid_large"
android:layout_marginEnd="@dimen/spacing_mid_large"
android:paddingStart="@dimen/spacing_insane"
android:paddingEnd="@dimen/spacing_insane"
android:text="@string/lbl_retry"
android:visibility="gone"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible" />
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View file

@ -8,6 +8,7 @@
<dimen name="spacing_mid_large">24dp</dimen>
<dimen name="spacing_large">32dp</dimen>
<dimen name="spacing_mid_huge">48dp</dimen>
<dimen name="spacing_huge">64dp</dimen>
<dimen name="spacing_insane">128dp</dimen>
<!-- Height Namespace | Height for UI elements -->

View file

@ -2,7 +2,6 @@
<resources>
<!-- COMPONENT-SPECIFIC STYLES. NOT RE-USABLE. -->
<!-- Style for the play/pause circle button -->
<style name="Widget.Component.Playback.PlayPause" parent="">
<item name="android:layout_height">@dimen/size_play_pause</item>
<item name="android:layout_width">@dimen/size_play_pause</item>
@ -18,7 +17,6 @@
<item name="android:padding">@dimen/spacing_medium</item>
</style>
<!-- Style for text used in widgets -->
<style name="Widget.Component.AppWidget.TextView" parent="Widget.AppCompat.TextView">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
@ -77,4 +75,8 @@
<style name="Widget.Component.AppWidget.Panel" parent="Widget.Component.AppWidget.Panel.Base">
<item name="android:elevation">@dimen/elevation_normal</item>
</style>
<style name="Widget.Component.Loading.ImageView.Icon" parent="">
<item name="android:src">@drawable/ic_launcher_foreground</item>
</style>
</resources>