style(android): clear detekt findings in PlayerController

- Two TooGenericExceptionCaught: connectAndObserve + connectController
    both catch Exception over Media3 IPC boundaries where specific-
    exception handling buys nothing (ListenableFuture.get() throws
    ExecutionException / InterruptedException / CancellationException —
    all forwarded uniformly). Widened to Throwable and @Suppressed with
    a one-line rationale each.
  - MaxLineLength: refactored TrackRef.toMediaItem's nested
    `.apply { source?.let { setExtras(Bundle()...) } }` chain into a
    pair of expression-bodied helpers (metadata builder + sourceExtras).
    Reads cleaner; under 120 chars.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-23 22:22:14 -04:00
parent 4fde634074
commit 6aec03fc02
@@ -2,6 +2,7 @@ package com.fabledsword.minstrel.player
import android.content.ComponentName
import android.content.Context
import android.os.Bundle
import androidx.media3.common.MediaItem
import androidx.media3.common.MediaMetadata
import androidx.media3.common.Player
@@ -90,7 +91,12 @@ class PlayerController @Inject constructor(
val controller =
try {
connectController()
} catch (e: Exception) {
} catch (
// Service-connection failure is a "show error, move on" boundary —
// any throwable from the Media3 IPC handshake gets surfaced via
// playbackError. Specific-exception handling buys nothing here.
@Suppress("TooGenericExceptionCaught") e: Throwable,
) {
uiStateInternal.value =
uiStateInternal.value.copy(playbackError = e.message ?: "Player unavailable")
return
@@ -132,7 +138,13 @@ class PlayerController @Inject constructor(
{
try {
cont.resume(future.get())
} catch (e: Exception) {
} catch (
// ListenableFuture.get() throws ExecutionException +
// InterruptedException + CancellationException — handle
// them uniformly by forwarding to the continuation;
// the caller catches at the outer boundary.
@Suppress("TooGenericExceptionCaught") e: Throwable,
) {
cont.resumeWithException(e)
}
},
@@ -141,19 +153,24 @@ class PlayerController @Inject constructor(
cont.invokeOnCancellation { future.cancel(/* mayInterruptIfRunning = */ false) }
}
private fun TrackRef.toMediaItem(source: String?): MediaItem =
MediaItem.Builder()
private fun TrackRef.toMediaItem(source: String?): MediaItem {
val metadata = MediaMetadata.Builder()
.setTitle(title)
.setArtist(artistName)
.setAlbumTitle(albumTitle)
.apply {
if (source != null) setExtras(sourceExtras(source))
}
.build()
return MediaItem.Builder()
.setMediaId(id)
.setUri(streamUrl)
.setMediaMetadata(
MediaMetadata.Builder()
.setTitle(title)
.setArtist(artistName)
.setAlbumTitle(albumTitle)
.apply { source?.let { setExtras(android.os.Bundle().apply { putString(MINSTREL_SOURCE_KEY, it) }) } }
.build(),
)
.setMediaMetadata(metadata)
.build()
}
private fun sourceExtras(source: String): Bundle =
Bundle().apply { putString(MINSTREL_SOURCE_KEY, source) }
companion object {
const val MINSTREL_SOURCE_KEY: String = "minstrel_source"