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:
parent
eaf3602bba
commit
d0b945dc9f
@ -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 {
|
||||||
|
|||||||
@ -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") {
|
||||||
|
|||||||
@ -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,15 +512,26 @@ private fun StationPickerSheet(
|
|||||||
),
|
),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
Icon(
|
if (!station.favicon.isNullOrBlank()) {
|
||||||
imageVector = Icons.Default.Radio,
|
AsyncImage(
|
||||||
contentDescription = null,
|
model = station.favicon,
|
||||||
tint = if (station.index == currentStation)
|
contentDescription = "Station logo",
|
||||||
MaterialTheme.colorScheme.onPrimary
|
modifier = Modifier
|
||||||
else
|
.size(40.dp)
|
||||||
MaterialTheme.colorScheme.onPrimaryContainer,
|
.clip(CircleShape),
|
||||||
modifier = Modifier.size(24.dp)
|
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) }
|
modifier = Modifier.clickable { onStationSelected(station.index) }
|
||||||
|
|||||||
@ -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) }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user