Files
radiola-android/app/src/main/java/com/radiola/ui/charts/ChartsViewModel.kt
nk 99503fc77a feat(charts): фильтр по жанру + жанр/стиль/лейбл/год на детальной трека
Подтягиваем обогащённые данные с бэкенда (Discogs): genre/styles/label/year
в чартах и детальной странице.

- ChartEntry/TrackStats + DTO: добавлены genre/styles/label/year
- RadiolaApi: getCharts(?genre=), новый getGenres()
- ChartsViewModel: состояние выбранного жанра + список жанров, перезагрузка
- ChartsScreen: ряд чипов-фильтров по жанру (Все + жанры),
  жанр/стили чипами и «Лейбл · Год» на детальной
- убран демо-fallback (SAMPLE_CHARTS) — бэкенд живой

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 13:55:35 +03:00

120 lines
4.1 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.radiola.ui.charts
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.radiola.domain.model.ChartEntry
import com.radiola.domain.model.ChartPeriod
import com.radiola.domain.model.TrackStats
import com.radiola.domain.repository.ChartsRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class ChartsViewModel @Inject constructor(
private val chartsRepository: ChartsRepository
) : ViewModel() {
private val _period = MutableStateFlow(ChartPeriod.WEEK)
val period: StateFlow<ChartPeriod> = _period.asStateFlow()
private val _charts = MutableStateFlow<List<ChartEntry>>(emptyList())
val charts: StateFlow<List<ChartEntry>> = _charts.asStateFlow()
/** Доступные жанры для фильтра (с бэкенда). */
private val _genres = MutableStateFlow<List<String>>(emptyList())
val genres: StateFlow<List<String>> = _genres.asStateFlow()
/** Выбранный жанр (null — «Все»). */
private val _selectedGenre = MutableStateFlow<String?>(null)
val selectedGenre: StateFlow<String?> = _selectedGenre.asStateFlow()
private val _isLoadingCharts = MutableStateFlow(false)
val isLoadingCharts: StateFlow<Boolean> = _isLoadingCharts.asStateFlow()
private val _selectedTrackStats = MutableStateFlow<TrackStats?>(null)
val selectedTrackStats: StateFlow<TrackStats?> = _selectedTrackStats.asStateFlow()
private val _isLoadingStats = MutableStateFlow(false)
val isLoadingStats: StateFlow<Boolean> = _isLoadingStats.asStateFlow()
init {
loadCharts()
loadGenres()
}
fun selectPeriod(newPeriod: ChartPeriod) {
if (_period.value == newPeriod) return
_period.value = newPeriod
loadCharts()
}
fun selectGenre(genre: String?) {
if (_selectedGenre.value == genre) return
_selectedGenre.value = genre
loadCharts()
}
fun selectTrack(trackId: String) {
viewModelScope.launch {
_isLoadingStats.value = true
_selectedTrackStats.value = null
try {
val stats = chartsRepository.getTrackStats(trackId)
_selectedTrackStats.value = stats
} catch (e: Exception) {
Log.e("ChartsViewModel", "Ошибка загрузки статистики трека $trackId", e)
} finally {
_isLoadingStats.value = false
}
}
}
fun clearSelection() {
_selectedTrackStats.value = null
}
fun toggleLike(trackId: String) {
val stats = _selectedTrackStats.value ?: return
val newLiked = !stats.isLiked
// Оптимистично обновляем UI
_selectedTrackStats.value = stats.copy(
isLiked = newLiked,
totalLikes = if (newLiked) stats.totalLikes + 1 else stats.totalLikes - 1
)
viewModelScope.launch {
try {
chartsRepository.setLiked(trackId, newLiked)
} catch (e: Exception) {
Log.e("ChartsViewModel", "Ошибка переключения лайка трека $trackId", e)
// Откатываем при ошибке
_selectedTrackStats.value = stats
}
}
}
private fun loadCharts() {
viewModelScope.launch {
_isLoadingCharts.value = true
try {
_charts.value = chartsRepository.getCharts(_period.value, _selectedGenre.value)
} catch (e: Exception) {
Log.e("ChartsViewModel", "Ошибка загрузки чартов", e)
_charts.value = emptyList()
} finally {
_isLoadingCharts.value = false
}
}
}
private fun loadGenres() {
viewModelScope.launch {
_genres.value = chartsRepository.getGenres()
}
}
}