diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt
index 8462a6521..99d853e90 100644
--- a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt
@@ -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 ---
diff --git a/app/src/main/java/org/oxycblt/auxio/loading/LoadingFragment.kt b/app/src/main/java/org/oxycblt/auxio/loading/LoadingFragment.kt
index 4e2eb89da..f9f69c31d 100644
--- a/app/src/main/java/org/oxycblt/auxio/loading/LoadingFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/loading/LoadingFragment.kt
@@ -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
diff --git a/app/src/main/java/org/oxycblt/auxio/music/Models.kt b/app/src/main/java/org/oxycblt/auxio/music/Models.kt
index 80fc7e121..ec14021e6 100644
--- a/app/src/main/java/org/oxycblt/auxio/music/Models.kt
+++ b/app/src/main/java/org/oxycblt/auxio/music/Models.kt
@@ -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
- }
}
/**
diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt
index ece93cb43..8ae0ee32b 100644
--- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt
@@ -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
diff --git a/app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt b/app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt
index 7d78913bb..4185cca48 100644
--- a/app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt
@@ -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 ---
diff --git a/app/src/main/res/layout/fragment_loading.xml b/app/src/main/res/layout/fragment_loading.xml
index 24032b656..db43f6af4 100644
--- a/app/src/main/res/layout/fragment_loading.xml
+++ b/app/src/main/res/layout/fragment_loading.xml
@@ -16,73 +16,61 @@
android:gravity="center"
android:orientation="vertical">
-
+
-
+ app:layout_constraintTop_toTopOf="parent" />
-
-
+ app:layout_constraintStart_toStartOf="parent" />
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index a6f1393ae..988ea6876 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -8,6 +8,7 @@
24dp
32dp
48dp
+ 64dp
128dp
diff --git a/app/src/main/res/values/styles_component.xml b/app/src/main/res/values/styles_component.xml
index b394598fb..736d583b2 100644
--- a/app/src/main/res/values/styles_component.xml
+++ b/app/src/main/res/values/styles_component.xml
@@ -2,7 +2,6 @@
-
-
+
+
\ No newline at end of file