mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-10 15:11:58 +01:00
fix lint and session access from the notification star review
- opt in to the Media3 unstable API on the service and answer unsupported custom commands with SessionError.ERROR_NOT_SUPPORTED - add the star command on top of the trust-aware connection defaults instead of granting untrusted controllers the full command set - number tracks within their disc, not across the whole album - leave the star button to the library flow so a failed write cannot leave the notification flipped - omit the leading cell entirely when a row has no art and no track
This commit is contained in:
@@ -22,6 +22,7 @@ import androidx.media3.session.CommandButton
|
||||
import androidx.media3.session.MediaSession
|
||||
import androidx.media3.session.MediaSessionService
|
||||
import androidx.media3.session.SessionCommand
|
||||
import androidx.media3.session.SessionError
|
||||
import androidx.media3.session.SessionResult
|
||||
import coil3.SingletonImageLoader
|
||||
import com.google.common.util.concurrent.Futures
|
||||
@@ -39,6 +40,7 @@ import kotlinx.coroutines.launch
|
||||
import okhttp3.OkHttpClient
|
||||
import org.koin.core.context.GlobalContext
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
class PlaybackService : MediaSessionService() {
|
||||
private var session: MediaSession? = null
|
||||
private var artworkLoader: CoverArtBitmapLoader? = null
|
||||
@@ -55,15 +57,17 @@ class PlaybackService : MediaSessionService() {
|
||||
override fun onConnect(
|
||||
session: MediaSession,
|
||||
controller: MediaSession.ControllerInfo,
|
||||
): MediaSession.ConnectionResult =
|
||||
MediaSession.ConnectionResult
|
||||
.AcceptedResultBuilder(session)
|
||||
): MediaSession.ConnectionResult {
|
||||
val base = MediaSession.ConnectionResult.AcceptedResultBuilder(session, controller).build()
|
||||
return MediaSession.ConnectionResult
|
||||
.AcceptedResultBuilder(session, controller)
|
||||
.setAvailableSessionCommands(
|
||||
MediaSession.ConnectionResult.DEFAULT_SESSION_COMMANDS
|
||||
base.availableSessionCommands
|
||||
.buildUpon()
|
||||
.add(STAR_COMMAND)
|
||||
.build(),
|
||||
).build()
|
||||
}
|
||||
|
||||
override fun onCustomCommand(
|
||||
session: MediaSession,
|
||||
@@ -72,7 +76,7 @@ class PlaybackService : MediaSessionService() {
|
||||
args: Bundle,
|
||||
): ListenableFuture<SessionResult> {
|
||||
if (customCommand.customAction != STAR_COMMAND.customAction) {
|
||||
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_ERROR_NOT_SUPPORTED))
|
||||
return Futures.immediateFuture(SessionResult(SessionError.ERROR_NOT_SUPPORTED))
|
||||
}
|
||||
toggleStar()
|
||||
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
|
||||
@@ -163,8 +167,7 @@ class PlaybackService : MediaSessionService() {
|
||||
private fun toggleStar() {
|
||||
val songId = currentSongId ?: return
|
||||
val library = library ?: return
|
||||
starred = !starred
|
||||
library.star(StarType.Song, songId, starred)
|
||||
library.star(StarType.Song, songId, !starred)
|
||||
}
|
||||
|
||||
private fun starButton(isStarred: Boolean): CommandButton =
|
||||
@@ -190,7 +193,6 @@ class PlaybackService : MediaSessionService() {
|
||||
}.build()
|
||||
|
||||
override fun onDestroy() {
|
||||
starJob?.cancel()
|
||||
scope.cancel()
|
||||
artworkLoader?.shutdown()
|
||||
artworkLoader = null
|
||||
|
||||
@@ -132,6 +132,16 @@ fun AlbumDetailScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
val discOrdinals =
|
||||
remember(songs) {
|
||||
val counters = mutableMapOf<Long, Long>()
|
||||
songs.associate { song ->
|
||||
val disc = song.disc ?: 1L
|
||||
val ordinal = (counters[disc] ?: 0L) + 1
|
||||
counters[disc] = ordinal
|
||||
song.id to ordinal
|
||||
}
|
||||
}
|
||||
HeroDetailScaffold(
|
||||
artwork = artwork,
|
||||
title = album?.name.orEmpty(),
|
||||
@@ -171,7 +181,7 @@ fun AlbumDetailScreen(
|
||||
SongRow(
|
||||
song = song,
|
||||
isPlaying = song.id == playingSongId,
|
||||
trackNumber = song.track ?: (index + 1).toLong(),
|
||||
trackNumber = song.track ?: discOrdinals[song.id],
|
||||
durationSeconds = song.duration,
|
||||
download = downloads[song.id],
|
||||
modifier =
|
||||
|
||||
@@ -57,16 +57,24 @@ fun SongRow(
|
||||
ListItem(
|
||||
modifier = modifier,
|
||||
leadingContent =
|
||||
if (coverArt != null) {
|
||||
{
|
||||
CoverArtCell(
|
||||
ref = coverArt(coverArtId, true),
|
||||
name = song.album ?: song.title,
|
||||
isPlaying = isPlaying,
|
||||
)
|
||||
when {
|
||||
coverArt != null -> {
|
||||
{
|
||||
CoverArtCell(
|
||||
ref = coverArt(coverArtId, true),
|
||||
name = song.album ?: song.title,
|
||||
isPlaying = isPlaying,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
trackNumber != null || isPlaying -> {
|
||||
{ TrackCell(trackNumber, isPlaying) }
|
||||
}
|
||||
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
{ TrackCell(trackNumber, isPlaying) }
|
||||
},
|
||||
trailingContent = {
|
||||
Row(
|
||||
|
||||
Reference in New Issue
Block a user