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 78fe928229
commit c3afcb4edc
4 changed files with 36 additions and 12 deletions

View File

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

View File

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

View File

@ -499,7 +499,6 @@ private fun StationPickerSheet(
items(stations) { station ->
ListItem(
headlineContent = { Text(station.name) },
supportingContent = { Text("Station ${station.index}") },
leadingContent = {
Box(
modifier = Modifier
@ -513,15 +512,26 @@ private fun StationPickerSheet(
),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Default.Radio,
contentDescription = null,
tint = if (station.index == currentStation)
MaterialTheme.colorScheme.onPrimary
else
MaterialTheme.colorScheme.onPrimaryContainer,
modifier = Modifier.size(24.dp)
)
if (!station.favicon.isNullOrBlank()) {
AsyncImage(
model = station.favicon,
contentDescription = "Station logo",
modifier = Modifier
.size(40.dp)
.clip(CircleShape),
contentScale = ContentScale.Crop
)
} else {
Icon(
imageVector = Icons.Default.Radio,
contentDescription = null,
tint = if (station.index == currentStation)
MaterialTheme.colorScheme.onPrimary
else
MaterialTheme.colorScheme.onPrimaryContainer,
modifier = Modifier.size(24.dp)
)
}
}
},
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 dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@ -227,9 +229,20 @@ class MainViewModel @Inject constructor(
karadioRepository.getStationList(serverAddress, maxStations = 50)
.onSuccess { stations ->
// Show stations immediately, then enrich with favicons
_uiState.update {
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 {
_uiState.update { it.copy(isLoadingStations = false) }