From 15e15c6664f2590fcbc1248e8ffbf61432e29690 Mon Sep 17 00:00:00 2001 From: nk Date: Mon, 1 Jun 2026 13:06:08 +0300 Subject: [PATCH] feat(ui): add SettingsScreen and SettingsViewModel --- .../com/radiola/ui/settings/SettingsScreen.kt | 104 ++++++++++++++++++ .../radiola/ui/settings/SettingsViewModel.kt | 48 ++++++++ 2 files changed, 152 insertions(+) create mode 100644 app/src/main/java/com/radiola/ui/settings/SettingsScreen.kt create mode 100644 app/src/main/java/com/radiola/ui/settings/SettingsViewModel.kt diff --git a/app/src/main/java/com/radiola/ui/settings/SettingsScreen.kt b/app/src/main/java/com/radiola/ui/settings/SettingsScreen.kt new file mode 100644 index 0000000..01c37ca --- /dev/null +++ b/app/src/main/java/com/radiola/ui/settings/SettingsScreen.kt @@ -0,0 +1,104 @@ +package com.radiola.ui.settings + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import com.radiola.domain.model.DeeplinkService + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SettingsScreen( + modifier: Modifier = Modifier, + viewModel: SettingsViewModel = hiltViewModel() +) { + val sleepTimer by viewModel.sleepTimerMinutes.collectAsState() + val enabledServices by viewModel.enabledServices.collectAsState() + val equalizerPreset by viewModel.equalizerPreset.collectAsState() + val isRecordingEnabled by viewModel.isRecordingEnabled.collectAsState() + val presets = listOf("Flat", "Rock", "Pop", "Jazz", "Bass") + + Scaffold( + topBar = { + TopAppBar( + title = { Text("Настройки") }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.background + ) + ) + } + ) { padding -> + LazyColumn( + modifier = modifier + .fillMaxSize() + .padding(padding), + contentPadding = PaddingValues(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + item { + Text("Таймер сна", style = MaterialTheme.typography.titleMedium) + Slider( + value = sleepTimer.toFloat(), + onValueChange = { viewModel.setSleepTimer(it.toInt()) }, + valueRange = 5f..120f, + steps = 22 + ) + Text("$sleepTimer мин", style = MaterialTheme.typography.bodyMedium) + } + item { + Text("Эквалайзер", style = MaterialTheme.typography.titleMedium) + SingleChoiceSegmentedButtonRow { + presets.forEach { preset -> + SegmentedButton( + selected = equalizerPreset == preset, + onClick = { viewModel.setEqualizerPreset(preset) }, + shape = MaterialTheme.shapes.small + ) { + Text(preset) + } + } + } + } + item { + Text("Музыкальные сервисы", style = MaterialTheme.typography.titleMedium) + Column { + DeeplinkService.entries.forEach { service -> + val checked = service.serviceId in enabledServices + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { viewModel.toggleService(service.serviceId, !checked) } + .padding(vertical = 12.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(service.displayName) + Switch( + checked = checked, + onCheckedChange = { viewModel.toggleService(service.serviceId, it) } + ) + } + } + } + } + item { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { viewModel.setRecordingEnabled(!isRecordingEnabled) } + .padding(vertical = 12.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text("Запись эфира") + Switch( + checked = isRecordingEnabled, + onCheckedChange = { viewModel.setRecordingEnabled(it) } + ) + } + } + } + } +} diff --git a/app/src/main/java/com/radiola/ui/settings/SettingsViewModel.kt b/app/src/main/java/com/radiola/ui/settings/SettingsViewModel.kt new file mode 100644 index 0000000..31cc451 --- /dev/null +++ b/app/src/main/java/com/radiola/ui/settings/SettingsViewModel.kt @@ -0,0 +1,48 @@ +package com.radiola.ui.settings + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.radiola.domain.model.DeeplinkService +import com.radiola.domain.repository.SettingsRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class SettingsViewModel @Inject constructor( + private val settingsRepository: SettingsRepository +) : ViewModel() { + + val sleepTimerMinutes: StateFlow = settingsRepository.getSleepTimerMinutes() + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), 30) + + val enabledServices: StateFlow> = settingsRepository.getEnabledDeeplinkServices() + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptySet()) + + val equalizerPreset: StateFlow = settingsRepository.getEqualizerPreset() + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), "Flat") + + val isRecordingEnabled: StateFlow = settingsRepository.isRecordingEnabled() + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false) + + fun setSleepTimer(minutes: Int) { + viewModelScope.launch { settingsRepository.setSleepTimerMinutes(minutes) } + } + + fun toggleService(serviceId: String, enabled: Boolean) { + viewModelScope.launch { + val current = enabledServices.value.toMutableSet() + if (enabled) current.add(serviceId) else current.remove(serviceId) + settingsRepository.setEnabledDeeplinkServices(current) + } + } + + fun setEqualizerPreset(preset: String) { + viewModelScope.launch { settingsRepository.setEqualizerPreset(preset) } + } + + fun setRecordingEnabled(enabled: Boolean) { + viewModelScope.launch { settingsRepository.setRecordingEnabled(enabled) } + } +}