diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailGenerator.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailGenerator.kt
index bd5356df5..0b48b060c 100644
--- a/app/src/main/java/org/oxycblt/auxio/detail/DetailGenerator.kt
+++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailGenerator.kt
@@ -1,9 +1,26 @@
+/*
+ * Copyright (c) 2024 Auxio Project
+ * DetailGenerator.kt is part of Auxio.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
package org.oxycblt.auxio.detail
-import android.content.Context
import androidx.annotation.StringRes
+import javax.inject.Inject
import org.oxycblt.auxio.R
-import org.oxycblt.auxio.detail.list.DiscHeader
import org.oxycblt.auxio.list.ListSettings
import org.oxycblt.auxio.list.sort.Sort
import org.oxycblt.auxio.music.Album
@@ -18,15 +35,18 @@ import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.info.Disc
import org.oxycblt.auxio.music.info.ReleaseType
import org.oxycblt.auxio.util.logD
-import java.util.SortedMap
-import javax.inject.Inject
interface DetailGenerator {
fun any(uid: Music.UID): Detail?
+
fun album(uid: Music.UID): Detail?
+
fun artist(uid: Music.UID): Detail?
+
fun genre(uid: Music.UID): Detail?
+
fun playlist(uid: Music.UID): Detail?
+
fun release()
interface Factory {
@@ -38,10 +58,10 @@ interface DetailGenerator {
}
}
-class DetailGeneratorFactoryImpl @Inject constructor(
- private val listSettings: ListSettings,
- private val musicRepository: MusicRepository
-) : DetailGenerator.Factory {
+class DetailGeneratorFactoryImpl
+@Inject
+constructor(private val listSettings: ListSettings, private val musicRepository: MusicRepository) :
+ DetailGenerator.Factory {
override fun create(invalidator: DetailGenerator.Invalidator): DetailGenerator =
DetailGeneratorImpl(invalidator, listSettings, musicRepository)
}
@@ -102,11 +122,12 @@ private class DetailGeneratorImpl(
val album = musicRepository.deviceLibrary?.findAlbum(uid) ?: return null
val songs = listSettings.albumSongSort.songs(album.songs)
val discs = songs.groupBy { it.disc }
- val section = if (discs.size > 1 || discs.keys.first() != null) {
- DetailSection.Discs(discs)
- } else {
- DetailSection.Songs(songs)
- }
+ val section =
+ if (discs.size > 1 || discs.keys.first() != null) {
+ DetailSection.Discs(discs)
+ } else {
+ DetailSection.Songs(songs)
+ }
return Detail(album, listOf(section))
}
@@ -138,13 +159,14 @@ private class DetailGeneratorImpl(
// implicit album list into the mapping.
logD("Implicit albums present, adding to list")
@Suppress("UNCHECKED_CAST")
- (grouping as MutableMap>)[DetailSection.Albums.Category.APPEARANCES] =
- artist.implicitAlbums
+ (grouping as MutableMap>)[
+ DetailSection.Albums.Category.APPEARANCES] = artist.implicitAlbums
}
- val sections = grouping.mapTo(mutableListOf()) { (category, albums) ->
- DetailSection.Albums(category, ARTIST_ALBUM_SORT.albums(albums))
- }
+ val sections =
+ grouping.mapTo(mutableListOf()) { (category, albums) ->
+ DetailSection.Albums(category, ARTIST_ALBUM_SORT.albums(albums))
+ }
val songs = DetailSection.Songs(listSettings.artistSongSort.songs(artist.songs))
sections.add(songs)
return Detail(artist, sections)
@@ -184,7 +206,8 @@ sealed interface DetailSection {
override val stringRes = R.string.lbl_songs
}
- data class Albums(val category: Category, override val items: List) : PlainSection() {
+ data class Albums(val category: Category, override val items: List) :
+ PlainSection() {
override val order = 1 + category.ordinal
override val stringRes = category.stringRes
@@ -203,7 +226,6 @@ sealed interface DetailSection {
}
}
-
data class Songs(override val items: List) : PlainSection() {
override val order = 12
override val stringRes = R.string.lbl_songs
diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailModule.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailModule.kt
index 4d41529db..2fde9b6a6 100644
--- a/app/src/main/java/org/oxycblt/auxio/detail/DetailModule.kt
+++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailModule.kt
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2024 Auxio Project
- * HomeModule.kt is part of Auxio.
+ * DetailModule.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt
index 03390b2a1..d5fbc9806 100644
--- a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt
+++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt
@@ -74,7 +74,6 @@ constructor(
) : ViewModel(), DetailGenerator.Invalidator {
private val detailGenerator = detailGeneratorFactory.create(this)
-
private val _toShow = MutableEvent()
/**
* A [Show] command that is awaiting a view capable of responding to it. Null if none currently.
@@ -208,21 +207,18 @@ constructor(
val album = detailGenerator.album(currentAlbum.value?.uid ?: return)
refreshDetail(album, _currentAlbum, _albumSongList, _albumSongInstructions, replace)
}
-
MusicType.ARTISTS -> {
val artist = detailGenerator.artist(currentArtist.value?.uid ?: return)
- refreshDetail(artist, _currentArtist, _artistSongList, _artistSongInstructions, replace)
+ refreshDetail(
+ artist, _currentArtist, _artistSongList, _artistSongInstructions, replace)
}
-
MusicType.GENRES -> {
val genre = detailGenerator.genre(currentGenre.value?.uid ?: return)
refreshDetail(genre, _currentGenre, _genreSongList, _genreSongInstructions, replace)
}
-
MusicType.PLAYLISTS -> {
refreshPlaylist(currentPlaylist.value?.uid ?: return)
}
-
else -> error("Unexpected music type $type")
}
}
@@ -522,7 +518,6 @@ constructor(
}
}
-
private fun refreshDetail(
detail: Detail?,
parent: MutableStateFlow,
@@ -537,24 +532,23 @@ constructor(
val newList = mutableListOf- ()
var newInstructions: UpdateInstructions = UpdateInstructions.Diff
for ((i, section) in detail.sections.withIndex()) {
- val items = when (section) {
- is DetailSection.PlainSection<*> -> {
- val header = if (section is DetailSection.Songs)
- SortHeader(section.stringRes) else BasicHeader(section.stringRes)
- newList.add(Divider(header))
- newList.add(header)
- section.items
- }
-
- is DetailSection.Discs -> {
- val header = BasicHeader(section.stringRes)
- newList.add(Divider(header))
- newList.add(header)
- section.discs.flatMap {
- listOf(DiscHeader(it.key)) + it.value
+ val items =
+ when (section) {
+ is DetailSection.PlainSection<*> -> {
+ val header =
+ if (section is DetailSection.Songs) SortHeader(section.stringRes)
+ else BasicHeader(section.stringRes)
+ newList.add(Divider(header))
+ newList.add(header)
+ section.items
+ }
+ is DetailSection.Discs -> {
+ val header = BasicHeader(section.stringRes)
+ newList.add(Divider(header))
+ newList.add(header)
+ section.discs.flatMap { listOf(DiscHeader(it.key)) + it.value }
}
}
- }
// Currently only the final section (songs, which can be sorted) are invalidatable
// and thus need to be replaced.
if (replace == -1 && i == detail.sections.lastIndex) {
@@ -568,12 +562,16 @@ constructor(
instructions.put(newInstructions)
}
- private fun refreshPlaylist(uid: Music.UID, instructions: UpdateInstructions = UpdateInstructions.Diff) {
+ private fun refreshPlaylist(
+ uid: Music.UID,
+ instructions: UpdateInstructions = UpdateInstructions.Diff
+ ) {
logD("Refreshing playlist list")
val edited = editedPlaylist.value
if (edited == null) {
val playlist = detailGenerator.playlist(uid)
- refreshDetail(playlist, _currentPlaylist, _playlistSongList, _playlistSongInstructions, null)
+ refreshDetail(
+ playlist, _currentPlaylist, _playlistSongList, _playlistSongInstructions, null)
return
}
val list = mutableListOf
- ()
diff --git a/app/src/main/java/org/oxycblt/auxio/list/ListSettings.kt b/app/src/main/java/org/oxycblt/auxio/list/ListSettings.kt
index 37cb2cc23..7dcbfa13f 100644
--- a/app/src/main/java/org/oxycblt/auxio/list/ListSettings.kt
+++ b/app/src/main/java/org/oxycblt/auxio/list/ListSettings.kt
@@ -46,12 +46,19 @@ interface ListSettings : Settings {
interface Listener {
fun onSongSortChanged() {}
+
fun onAlbumSortChanged() {}
+
fun onAlbumSongSortChanged() {}
+
fun onArtistSortChanged() {}
+
fun onArtistSongSortChanged() {}
+
fun onGenreSortChanged() {}
+
fun onGenreSongSortChanged() {}
+
fun onPlaylistSortChanged() {}
}
}
diff --git a/app/src/main/java/org/oxycblt/auxio/music/service/MusicBrowser.kt b/app/src/main/java/org/oxycblt/auxio/music/service/MusicBrowser.kt
index 2a109204a..0e82b5d86 100644
--- a/app/src/main/java/org/oxycblt/auxio/music/service/MusicBrowser.kt
+++ b/app/src/main/java/org/oxycblt/auxio/music/service/MusicBrowser.kt
@@ -24,13 +24,8 @@ import javax.inject.Inject
import org.oxycblt.auxio.R
import org.oxycblt.auxio.detail.DetailGenerator
import org.oxycblt.auxio.detail.DetailSection
-import org.oxycblt.auxio.detail.list.SortHeader
import org.oxycblt.auxio.home.HomeGenerator
-import org.oxycblt.auxio.list.BasicHeader
-import org.oxycblt.auxio.list.Divider
-import org.oxycblt.auxio.list.ListSettings
import org.oxycblt.auxio.list.adapter.UpdateInstructions
-import org.oxycblt.auxio.list.sort.Sort
import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.Genre
@@ -98,13 +93,14 @@ private constructor(
override fun invalidate(type: MusicType, replace: Int?) {
val deviceLibrary = musicRepository.deviceLibrary ?: return
val userLibrary = musicRepository.userLibrary ?: return
- val music = when (type) {
- MusicType.ALBUMS -> deviceLibrary.albums
- MusicType.ARTISTS -> deviceLibrary.artists
- MusicType.GENRES -> deviceLibrary.genres
- MusicType.PLAYLISTS -> userLibrary.playlists
- else -> return
- }
+ val music =
+ when (type) {
+ MusicType.ALBUMS -> deviceLibrary.albums
+ MusicType.ARTISTS -> deviceLibrary.artists
+ MusicType.GENRES -> deviceLibrary.genres
+ MusicType.PLAYLISTS -> userLibrary.playlists
+ else -> return
+ }
if (music.isEmpty()) {
return
}
@@ -226,20 +222,23 @@ private constructor(
val detail = detailGenerator.any(uid) ?: return null
return detail.sections.flatMap { section ->
when (section) {
- is DetailSection.Songs -> section.items.map { it.toMediaItem(context, null, header(section.stringRes)) }
- is DetailSection.Albums -> section.items.map { it.toMediaItem(context, null, header(section.stringRes)) }
- is DetailSection.Artists -> section.items.map { it.toMediaItem(context, header(section.stringRes)) }
- is DetailSection.Discs -> section.discs.flatMap {
+ is DetailSection.Songs ->
+ section.items.map { it.toMediaItem(context, null, header(section.stringRes)) }
+ is DetailSection.Albums ->
+ section.items.map { it.toMediaItem(context, null, header(section.stringRes)) }
+ is DetailSection.Artists ->
+ section.items.map { it.toMediaItem(context, header(section.stringRes)) }
+ is DetailSection.Discs ->
section.discs.flatMap { entry ->
val disc = entry.key
- val discString = if (disc != null) {
- context.getString(R.string.fmt_disc_no, disc.number)
- } else {
- context.getString(R.string.def_disc)
- }
+ val discString =
+ if (disc != null) {
+ context.getString(R.string.fmt_disc_no, disc.number)
+ } else {
+ context.getString(R.string.def_disc)
+ }
entry.value.map { it.toMediaItem(context, null, header(discString)) }
}
- }
else -> error("Unknown section type: $section")
}
}
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackServiceFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackServiceFragment.kt
index d0c419ae1..9f77f714e 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackServiceFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackServiceFragment.kt
@@ -64,7 +64,7 @@ private constructor(
private val exoHolder = exoHolderFactory.create()
private val sessionHolder = sessionHolderFactory.create(context, foregroundListener)
private val widgetComponent = widgetComponentFactory.create(context)
- private val systemReceiver = systemReceiverFactory.create(context)
+ private val systemReceiver = systemReceiverFactory.create(context, widgetComponent)
val token: MediaSessionCompat.Token
get() = sessionHolder.token
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/SystemPlaybackReceiver.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/SystemPlaybackReceiver.kt
index 3a10039db..4a846cdfe 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/service/SystemPlaybackReceiver.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/service/SystemPlaybackReceiver.kt
@@ -47,10 +47,9 @@ private constructor(
@Inject
constructor(
private val playbackManager: PlaybackStateManager,
- private val playbackSettings: PlaybackSettings,
- private val widgetComponent: WidgetComponent
+ private val playbackSettings: PlaybackSettings
) {
- fun create(context: Context): SystemPlaybackReceiver {
+ fun create(context: Context, widgetComponent: WidgetComponent): SystemPlaybackReceiver {
val receiver =
SystemPlaybackReceiver(playbackManager, playbackSettings, widgetComponent)
ContextCompat.registerReceiver(
diff --git a/media b/media
index 34b33175c..9fc2401b8 160000
--- a/media
+++ b/media
@@ -1 +1 @@
-Subproject commit 34b33175c00183dc95cdcb8c735033b6785041e1
+Subproject commit 9fc2401b8fdc2b23905402462e775c6db4e1527f