Improve station picker with favicons and fix indexing

- Fix station list starting at index 0 instead of 1
- Fetch and display station favicons from RadioBrowser
- Remove redundant "Station X" text from list items
This commit is contained in:
Pavel Baksy 2025-11-22 23:26:06 +01:00
parent 14c901dd10
commit c792e24774
4 changed files with 36 additions and 12 deletions

View File

@ -14,7 +14,8 @@ data class KaradioStation(
val url: String, val url: String,
val path: String, val path: String,
val port: Int, val port: Int,
val volumeOffset: Int = 0 val volumeOffset: Int = 0,
val favicon: String? = null
) )
fun parseKaradioStatus(response: String): KaradioStatus { fun parseKaradioStatus(response: String): KaradioStatus {

View File

@ -99,7 +99,7 @@ class KaradioRepository @Inject constructor() {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
runCatching { runCatching {
val stations = mutableListOf<KaradioStation>() val stations = mutableListOf<KaradioStation>()
for (i in 1 until maxStations) { for (i in 0 until maxStations) {
val response = getApi(serverAddress).getStationName(i) val response = getApi(serverAddress).getStationName(i)
val name = parseStationNameResponse(response) val name = parseStationNameResponse(response)
if (name.isNotBlank() && name != "not set") { if (name.isNotBlank() && name != "not set") {

View File

@ -499,7 +499,6 @@ private fun StationPickerSheet(
items(stations) { station -> items(stations) { station ->
ListItem( ListItem(
headlineContent = { Text(station.name) }, headlineContent = { Text(station.name) },
supportingContent = { Text("Station ${station.index}") },
leadingContent = { leadingContent = {
Box( Box(
modifier = Modifier modifier = Modifier
@ -513,6 +512,16 @@ private fun StationPickerSheet(
), ),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
if (!station.favicon.isNullOrBlank()) {
AsyncImage(
model = station.favicon,
contentDescription = "Station logo",
modifier = Modifier
.size(40.dp)
.clip(CircleShape),
contentScale = ContentScale.Crop
)
} else {
Icon( Icon(
imageVector = Icons.Default.Radio, imageVector = Icons.Default.Radio,
contentDescription = null, contentDescription = null,
@ -523,6 +532,7 @@ private fun StationPickerSheet(
modifier = Modifier.size(24.dp) modifier = Modifier.size(24.dp)
) )
} }
}
}, },
modifier = Modifier.clickable { onStationSelected(station.index) } modifier = Modifier.clickable { onStationSelected(station.index) }
) )

View File

@ -10,6 +10,8 @@ import cz.bugsy.karemote.data.repository.RadioBrowserRepository
import cz.bugsy.karemote.data.repository.SettingsRepository import cz.bugsy.karemote.data.repository.SettingsRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
@ -227,9 +229,20 @@ class MainViewModel @Inject constructor(
karadioRepository.getStationList(serverAddress, maxStations = 50) karadioRepository.getStationList(serverAddress, maxStations = 50)
.onSuccess { stations -> .onSuccess { stations ->
// Show stations immediately, then enrich with favicons
_uiState.update { _uiState.update {
it.copy(stations = stations, isLoadingStations = false) it.copy(stations = stations, isLoadingStations = false)
} }
// Fetch favicons from RadioBrowser concurrently
val enrichedStations = stations.map { station ->
async {
val radioBrowserInfo = radioBrowserRepository.getStationInfo(station.name)
station.copy(favicon = radioBrowserInfo?.favicon)
}
}.awaitAll()
_uiState.update { it.copy(stations = enrichedStations) }
} }
.onFailure { .onFailure {
_uiState.update { it.copy(isLoadingStations = false) } _uiState.update { it.copy(isLoadingStations = false) }