fix(stations): обложки Record только для Record-станций + своя плитка остальным
- сети, отличные от Radio Record (DFM, HitFM и др.), больше не получают обложки Radio Record (обогащение Record API гейтится по source=record) - станции без обложки рисуют свою фирменную плитку: цвет по названию + инициалы (вместо общего значка/чужой обложки)
This commit is contained in:
@@ -29,16 +29,19 @@ class LocalStationDataSource @Inject constructor(
|
|||||||
.map { dto ->
|
.map { dto ->
|
||||||
val group = groupMap[dto.groupId]
|
val group = groupMap[dto.groupId]
|
||||||
val prefix = generatePrefix(dto.name)
|
val prefix = generatePrefix(dto.name)
|
||||||
|
// Определяем сеть: только станции Radio Record можно обогащать
|
||||||
|
// обложками из Record API. Остальные сети — свой источник.
|
||||||
|
val isRecord = dto.site?.contains("radiorecord", ignoreCase = true) == true
|
||||||
Station(
|
Station(
|
||||||
id = dto.id,
|
id = dto.id,
|
||||||
name = dto.name,
|
name = dto.name,
|
||||||
prefix = prefix,
|
prefix = prefix,
|
||||||
streamUrl = dto.stream!!,
|
streamUrl = dto.stream!!,
|
||||||
coverUrl = group?.let { generateCoverUrl(it.name, dto.name) } ?: "",
|
coverUrl = "",
|
||||||
genre = group?.name ?: "",
|
genre = group?.name ?: "",
|
||||||
tags = listOfNotNull(group?.name?.takeIf { it.isNotBlank() }),
|
tags = listOfNotNull(group?.name?.takeIf { it.isNotBlank() }),
|
||||||
sortOrder = dto.id,
|
sortOrder = dto.id,
|
||||||
source = "local"
|
source = if (isRecord) "record" else "local"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,10 +46,14 @@ class StationRepositoryImpl @Inject constructor(
|
|||||||
// нет prefix — поэтому сопоставляем сначала по id, затем по названию
|
// нет prefix — поэтому сопоставляем сначала по id, затем по названию
|
||||||
// (стабильный общий ключ), иначе обложки/потоки не подтягиваются.
|
// (стабильный общий ключ), иначе обложки/потоки не подтягиваются.
|
||||||
val merged = localStations.map { local ->
|
val merged = localStations.map { local ->
|
||||||
val apiStation = apiStations.find { it.id == local.id }
|
// Обложки/потоки из Record API — только для станций сети Radio Record.
|
||||||
?: apiStations.find {
|
// Иначе чужим сетям (DFM, HitFM и т.д.) цеплялись бы обложки Record.
|
||||||
it.name.trim().equals(local.name.trim(), ignoreCase = true)
|
val apiStation = if (local.source == "record") {
|
||||||
}
|
apiStations.find { it.id == local.id }
|
||||||
|
?: apiStations.find {
|
||||||
|
it.name.trim().equals(local.name.trim(), ignoreCase = true)
|
||||||
|
}
|
||||||
|
} else null
|
||||||
if (apiStation != null) {
|
if (apiStation != null) {
|
||||||
val domain = apiStation.toDomain()
|
val domain = apiStation.toDomain()
|
||||||
local.copy(
|
local.copy(
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
@@ -66,12 +68,21 @@ fun StationCard(
|
|||||||
contentScale = ContentScale.Crop
|
contentScale = ContentScale.Crop
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Icon(
|
// Своя фирменная плитка станции (цвет из названия + инициалы),
|
||||||
Lucide.Radio,
|
// а не общий значок и не чужая обложка.
|
||||||
contentDescription = null,
|
Box(
|
||||||
tint = colors.textMuted,
|
modifier = Modifier
|
||||||
modifier = Modifier.align(Alignment.Center).size(34.dp)
|
.fillMaxSize()
|
||||||
)
|
.background(stationTileBrush(station.name)),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stationInitials(station.name),
|
||||||
|
color = androidx.compose.ui.graphics.Color.White,
|
||||||
|
fontWeight = FontWeight.Black,
|
||||||
|
style = androidx.compose.material3.MaterialTheme.typography.headlineMedium
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -114,3 +125,22 @@ fun StationCard(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Инициалы станции для плитки-плейсхолдера (1–2 символа). */
|
||||||
|
private fun stationInitials(name: String): String {
|
||||||
|
val words = name.trim().split(Regex("\\s+")).filter { it.isNotBlank() }
|
||||||
|
return when {
|
||||||
|
words.isEmpty() -> "?"
|
||||||
|
words.size == 1 -> words[0].take(2).uppercase()
|
||||||
|
else -> (words[0].take(1) + words[1].take(1)).uppercase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Детерминированный фирменный градиент плитки по названию станции. */
|
||||||
|
private fun stationTileBrush(name: String): Brush {
|
||||||
|
val h = (name.hashCode().toLong() and 0xFFFFFFFFL)
|
||||||
|
val hue = (h % 360L).toFloat()
|
||||||
|
val c1 = Color.hsv(hue, 0.55f, 0.45f)
|
||||||
|
val c2 = Color.hsv((hue + 28f) % 360f, 0.6f, 0.30f)
|
||||||
|
return Brush.linearGradient(listOf(c1, c2))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user