diff --git a/app/src/main/java/org/oxycblt/auxio/music/Indexer.kt b/app/src/main/java/org/oxycblt/auxio/music/Indexer.kt index 319cc333e..33dedfceb 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/Indexer.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/Indexer.kt @@ -361,6 +361,12 @@ class Indexer { object NoPerms : Response() } + /** + * A callback to use when the indexing state changes. + * + * This callback is low-level and not guaranteed to be single-thread. For that, + * [MusicStore.Callback] is recommended instead. + */ interface Callback { /** * Called when the current state of the Indexer changed. diff --git a/app/src/main/java/org/oxycblt/auxio/music/IndexerService.kt b/app/src/main/java/org/oxycblt/auxio/music/IndexerService.kt index 4c9c98dfc..1fb1e5e9e 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/IndexerService.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/IndexerService.kt @@ -54,6 +54,7 @@ class IndexerService : Service(), Indexer.Callback { private val serviceJob = Job() private val indexScope = CoroutineScope(serviceJob + Dispatchers.Main) + private val updateScope = CoroutineScope(serviceJob + Dispatchers.Main) private var isForeground = false private lateinit var notification: IndexerNotification @@ -92,20 +93,21 @@ class IndexerService : Service(), Indexer.Callback { if (state.response is Indexer.Response.Ok && state.response.library != musicStore.library) { logD("Applying new library") + // Load was completed successfully, so apply the new library if we - // have not already. - musicStore.library = state.response.library + // have not already. Only when we are done updating the library will + // the service stop it's foreground state. + updateScope.launch { + musicStore.updateLibrary(state.response.library) + stopForegroundSession() + } + } else { + // On errors, while we would want to show a notification that displays the + // error, in practice that comes into conflict with the upcoming Android 13 + // notification permission, and there is no point implementing permission + // on-boarding for such when it will only be used for this. + stopForegroundSession() } - - // On errors, while we would want to show a notification that displays the - // error, in practice that comes into conflict with the upcoming Android 13 - // notification permission, and there is no point implementing permission - // on-boarding for such when it will only be used for this. - - // Note that we don't stop the service here, as (in the future) - // this service will be used to reload music and observe the music - // database. - stopForegroundSession() } is Indexer.State.Indexing -> { // When loading, we want to enter the foreground state so that android does diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt index e967ba74d..c70d785c4 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt @@ -20,6 +20,8 @@ package org.oxycblt.auxio.music import android.content.Context import android.net.Uri import android.provider.OpenableColumns +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import org.oxycblt.auxio.util.contentResolverSafe /** @@ -33,14 +35,7 @@ class MusicStore private constructor() { private val callbacks = mutableListOf() var library: Library? = null - set(value) { - synchronized(this) { - field = value - for (callback in callbacks) { - callback.onLibraryChanged(library) - } - } - } + private set /** Add a callback to this instance. Make sure to remove it when done. */ fun addCallback(callback: Callback) { @@ -53,6 +48,19 @@ class MusicStore private constructor() { callbacks.remove(callback) } + suspend fun updateLibrary(newLibrary: Library?) { + // Ensure we are on the main thread when updating the library, as callbacks expect to + // run in an stable app thread. + withContext(Dispatchers.Main) { + synchronized(this) { + library = newLibrary + for (callback in callbacks) { + callback.onLibraryChanged(library) + } + } + } + } + /** Represents a library of music owned by [MusicStore]. */ data class Library( val genres: List, @@ -80,7 +88,6 @@ class MusicStore private constructor() { songs.find { it.path.name == displayName } } - /** "Sanitize" a music object from a previous library iteration. */ fun sanitize(song: Song) = songs.find { it.id == song.id } fun sanitize(album: Album) = albums.find { it.id == album.id } fun sanitize(artist: Artist) = artists.find { it.id == artist.id } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt index edfb259f6..86fe8d29c 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt @@ -143,7 +143,6 @@ class PlaybackService : // --- PLAYBACKSTATEMANAGER SETUP --- settings = Settings(this, this) - playbackManager.registerController(this) logD("Service created") diff --git a/app/src/main/java/org/oxycblt/auxio/ui/Sort.kt b/app/src/main/java/org/oxycblt/auxio/ui/Sort.kt index f025d67e0..4fe015972 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/Sort.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/Sort.kt @@ -28,7 +28,7 @@ import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Song /** - * A data class representing the sort modes used in Auxio. + * Represents the sort modes used in Auxio. * * Sorting can be done by Name, Artist, Album, and others. Sorting of names is always * case-insensitive and article-aware. Certain datatypes may only support a subset of sorts since diff --git a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentGridLayoutManager.kt b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentGridLayoutManager.kt index 36513c9e1..8ce95604e 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentGridLayoutManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentGridLayoutManager.kt @@ -37,7 +37,7 @@ class AccentGridLayoutManager( ) : GridLayoutManager(context, attrs, defStyleAttr, defStyleRes) { // We use 72dp here since that's the rough size of the accent item. // This will need to be modified if this is used beyond the accent dialog. - private var columnWidth = context.pxOfDp(64f) + private var columnWidth = context.pxOfDp(56f) private var lastWidth = -1 private var lastHeight = -1 diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt b/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt index 8e311f0ba..944039e5c 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt @@ -100,7 +100,7 @@ private fun RemoteViews.applyCover( R.id.widget_cover, context.getString(R.string.desc_album_cover, state.song.album.resolveName(context))) } else { - setImageViewResource(R.id.widget_cover, R.drawable.ic_remote_default_cover) + setImageViewResource(R.id.widget_cover, R.drawable.ic_remote_default_cover_24) setContentDescription(R.id.widget_cover, context.getString(R.string.desc_no_cover)) } diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt index 8e4b6d205..46f395f4d 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt @@ -61,8 +61,7 @@ class WidgetComponent(private val context: Context) : */ fun update() { // TODO: Rework margins/button layout to do the magic that other button bars do - // TODO: Try to change the error icon again - // TODO: + // TODO: Respond to rounded covers // Updating Auxio's widget is unlike the rest of Auxio for a few reasons: // 1. We can't use the typical primitives like ViewModels diff --git a/app/src/main/res/drawable/ic_queue.xml b/app/src/main/res/drawable/ic_queue_24.xml similarity index 100% rename from app/src/main/res/drawable/ic_queue.xml rename to app/src/main/res/drawable/ic_queue_24.xml diff --git a/app/src/main/res/drawable/ic_remote_default_cover.xml b/app/src/main/res/drawable/ic_remote_default_cover_24.xml similarity index 100% rename from app/src/main/res/drawable/ic_remote_default_cover.xml rename to app/src/main/res/drawable/ic_remote_default_cover_24.xml diff --git a/app/src/main/res/layout/item_accent.xml b/app/src/main/res/layout/item_accent.xml index 0417a7036..ee8a398d4 100644 --- a/app/src/main/res/layout/item_accent.xml +++ b/app/src/main/res/layout/item_accent.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="@dimen/spacing_small" + android:padding="@dimen/spacing_tiny" android:theme="@style/ThemeOverlay.Accent"> diff --git a/app/src/main/res/layout/widget_wide.xml b/app/src/main/res/layout/widget_wide.xml index 1f7fed18e..18a1f9a67 100644 --- a/app/src/main/res/layout/widget_wide.xml +++ b/app/src/main/res/layout/widget_wide.xml @@ -37,7 +37,7 @@ android:layout_alignTop="@id/widget_aspect_ratio" android:layout_alignEnd="@id/widget_aspect_ratio" android:layout_alignBottom="@id/widget_aspect_ratio" - android:src="@drawable/ic_remote_default_cover" + android:src="@drawable/ic_remote_default_cover_24" tools:ignore="ContentDescription" /> 56dp - 16sp - 18sp 12sp - 20sp + 22sp 2sp