feat(ui): add SettingsScreen and SettingsViewModel

This commit is contained in:
nk
2026-06-01 13:06:08 +03:00
parent d3cec3bba2
commit 15e15c6664
2 changed files with 152 additions and 0 deletions

View File

@@ -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) }
)
}
}
}
}
}

View File

@@ -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<Int> = settingsRepository.getSleepTimerMinutes()
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), 30)
val enabledServices: StateFlow<Set<String>> = settingsRepository.getEnabledDeeplinkServices()
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptySet())
val equalizerPreset: StateFlow<String> = settingsRepository.getEqualizerPreset()
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), "Flat")
val isRecordingEnabled: StateFlow<Boolean> = 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) }
}
}