feat(player): 4 стиля визуализатора + выбор в настройках
Добавлены стили анимации воспроизведения: столбики от центра, столбики снизу (спектр), плавная волна, радиальный — все от реального спектра звука (Visualizer.kt). Пользователь выбирает стиль в Настройках → «Анимация воспроизведения» (живые превью каждого стиля, тап выбирает). Сохраняется пер-юзер (DataStore visualizer_style). Плеер рисует выбранный стиль (радиальный — повыше). Превью и пауза — мягкая «дышащая» анимация. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -41,6 +41,7 @@ fun SettingsScreen(
|
||||
val sleepTimer by viewModel.sleepTimerMinutes.collectAsState()
|
||||
val enabledServices by viewModel.enabledServices.collectAsState()
|
||||
val equalizerPreset by viewModel.equalizerPreset.collectAsState()
|
||||
val visualizerStyle by viewModel.visualizerStyle.collectAsState()
|
||||
val isRecordingEnabled by viewModel.isRecordingEnabled.collectAsState()
|
||||
val isTesting by viewModel.isTesting.collectAsState()
|
||||
val testProgress by viewModel.testProgress.collectAsState()
|
||||
@@ -231,6 +232,52 @@ fun SettingsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
// --- Стиль визуализации воспроизведения ---
|
||||
item {
|
||||
SectionLabel("АНИМАЦИЯ ВОСПРОИЗВЕДЕНИЯ")
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||
com.radiola.ui.components.VisualizerStyle.entries.chunked(2).forEach { rowStyles ->
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||
rowStyles.forEach { style ->
|
||||
val selected = visualizerStyle == style.key
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(colors.surface)
|
||||
.border(
|
||||
width = if (selected) 2.dp else 1.dp,
|
||||
color = if (selected) colors.accent else colors.border,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
)
|
||||
.clickable { viewModel.setVisualizerStyle(style.key) }
|
||||
.padding(12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
com.radiola.ui.components.Visualizer(
|
||||
style = style,
|
||||
levels = null,
|
||||
playing = true,
|
||||
color = colors.accent,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(48.dp)
|
||||
)
|
||||
Text(
|
||||
text = style.label,
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
color = if (selected) colors.accent else colors.textSecondary,
|
||||
fontWeight = if (selected) FontWeight.SemiBold else FontWeight.Normal
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Музыкальные сервисы ---
|
||||
item {
|
||||
SectionLabel("МУЗЫКАЛЬНЫЕ СЕРВИСЫ")
|
||||
|
||||
@@ -32,6 +32,9 @@ class SettingsViewModel @Inject constructor(
|
||||
val equalizerPreset: StateFlow<String> = settingsRepository.getEqualizerPreset()
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), "Flat")
|
||||
|
||||
val visualizerStyle: StateFlow<String> = settingsRepository.getVisualizerStyle()
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), "bars_center")
|
||||
|
||||
val isRecordingEnabled: StateFlow<Boolean> = settingsRepository.isRecordingEnabled()
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false)
|
||||
|
||||
@@ -69,6 +72,10 @@ class SettingsViewModel @Inject constructor(
|
||||
viewModelScope.launch { settingsRepository.setEqualizerPreset(preset) }
|
||||
}
|
||||
|
||||
fun setVisualizerStyle(style: String) {
|
||||
viewModelScope.launch { settingsRepository.setVisualizerStyle(style) }
|
||||
}
|
||||
|
||||
fun setRecordingEnabled(enabled: Boolean) {
|
||||
viewModelScope.launch { settingsRepository.setRecordingEnabled(enabled) }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user