feat(ui): add SettingsScreen and SettingsViewModel
This commit is contained in:
104
app/src/main/java/com/radiola/ui/settings/SettingsScreen.kt
Normal file
104
app/src/main/java/com/radiola/ui/settings/SettingsScreen.kt
Normal 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) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user