199 lines
6.7 KiB
XML
199 lines
6.7 KiB
XML
<WORK_ORDER feature="Settings Screen">
|
|
<ACTION type="MODIFY" file_path="./app/src/main/java/com/homebox/lens/navigation/Screen.kt">
|
|
<DESCRIPTION>Добавить маршрут для экрана настроек в sealed class Screen.</DESCRIPTION>
|
|
<INSERT after="// [END_ENTITY: Object('Search')]">
|
|
<![CDATA[
|
|
|
|
// [ENTITY: Object('Settings')]
|
|
data object Settings : Screen("settings_screen")
|
|
// [END_ENTITY: Object('Settings')]
|
|
]]>
|
|
</INSERT>
|
|
</ACTION>
|
|
|
|
<ACTION type="CREATE" file_path="./app/src/main/java/com/homebox/lens/ui/screen/settings/SettingsUiState.kt">
|
|
<DESCRIPTION>Создать data class для состояния UI экрана настроек.</DESCRIPTION>
|
|
<CONTENT>
|
|
<![CDATA[
|
|
package com.homebox.lens.ui.screen.settings
|
|
|
|
data class SettingsUiState(
|
|
val serverUrl: String = "",
|
|
val isLoading: Boolean = false,
|
|
val error: String? = null,
|
|
val isSaved: Boolean = false
|
|
)
|
|
]]>
|
|
</CONTENT>
|
|
</ACTION>
|
|
|
|
<ACTION type="CREATE" file_path="./app/src/main/java/com/homebox/lens/ui/screen/settings/SettingsViewModel.kt">
|
|
<DESCRIPTION>Создать ViewModel для экрана настроек.</DESCRIPTION>
|
|
<CONTENT>
|
|
<![CDATA[
|
|
package com.homebox.lens.ui.screen.settings
|
|
|
|
import androidx.lifecycle.ViewModel
|
|
import androidx.lifecycle.viewModelScope
|
|
import com.homebox.lens.domain.repository.CredentialsRepository
|
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
|
import kotlinx.coroutines.flow.MutableStateFlow
|
|
import kotlinx.coroutines.flow.asStateFlow
|
|
import kotlinx.coroutines.flow.first
|
|
import kotlinx.coroutines.launch
|
|
import javax.inject.Inject
|
|
|
|
@HiltViewModel
|
|
class SettingsViewModel @Inject constructor(
|
|
private val credentialsRepository: CredentialsRepository
|
|
) : ViewModel() {
|
|
|
|
private val _uiState = MutableStateFlow(SettingsUiState())
|
|
val uiState = _uiState.asStateFlow()
|
|
|
|
init {
|
|
loadCurrentSettings()
|
|
}
|
|
|
|
private fun loadCurrentSettings() {
|
|
viewModelScope.launch {
|
|
_uiState.value = _uiState.value.copy(isLoading = true)
|
|
val credentials = credentialsRepository.getCredentials().first()
|
|
_uiState.value = _uiState.value.copy(
|
|
serverUrl = credentials?.serverUrl ?: "",
|
|
isLoading = false
|
|
)
|
|
}
|
|
}
|
|
|
|
fun onServerUrlChange(newUrl: String) {
|
|
_uiState.value = _uiState.value.copy(serverUrl = newUrl, isSaved = false)
|
|
}
|
|
|
|
fun saveSettings() {
|
|
// TODO: Implement saving logic, probably need a use case
|
|
// For now, just simulate success
|
|
viewModelScope.launch {
|
|
_uiState.value = _uiState.value.copy(isLoading = true)
|
|
// val success = saveSettingsUseCase(_uiState.value.serverUrl)
|
|
_uiState.value = _uiState.value.copy(isLoading = false, isSaved = true)
|
|
}
|
|
}
|
|
}
|
|
]]>
|
|
</CONTENT>
|
|
</ACTION>
|
|
|
|
<ACTION type="CREATE" file_path="./app/src/main/java/com/homebox/lens/ui/screen/settings/SettingsScreen.kt">
|
|
<DESCRIPTION>Создать Composable для UI экрана настроек.</DESCRIPTION>
|
|
<CONTENT>
|
|
<![CDATA[
|
|
package com.homebox.lens.ui.screen.settings
|
|
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.material.icons.Icons
|
|
import androidx.compose.material.icons.filled.Settings
|
|
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.homebox.lens.navigation.Screen
|
|
import com.homebox.lens.ui.common.MainScaffold
|
|
|
|
@Composable
|
|
fun SettingsScreen(
|
|
viewModel: SettingsViewModel = hiltViewModel(),
|
|
onNavigateUp: () -> Unit
|
|
) {
|
|
val uiState by viewModel.uiState.collectAsState()
|
|
|
|
MainScaffold(
|
|
title = "Настройки",
|
|
onNavigateUp = onNavigateUp
|
|
) { paddingValues ->
|
|
SettingsContent(
|
|
modifier = Modifier.padding(paddingValues),
|
|
uiState = uiState,
|
|
onServerUrlChange = viewModel::onServerUrlChange,
|
|
onSaveClick = viewModel::saveSettings
|
|
)
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
fun SettingsContent(
|
|
modifier: Modifier = Modifier,
|
|
uiState: SettingsUiState,
|
|
onServerUrlChange: (String) -> Unit,
|
|
onSaveClick: () -> Unit
|
|
) {
|
|
Column(
|
|
modifier = modifier
|
|
.fillMaxSize()
|
|
.padding(16.dp)
|
|
) {
|
|
OutlinedTextField(
|
|
value = uiState.serverUrl,
|
|
onValueChange = onServerUrlChange,
|
|
label = { Text("URL Сервера") },
|
|
modifier = Modifier.fillMaxWidth()
|
|
)
|
|
Spacer(modifier = Modifier.height(16.dp))
|
|
Button(
|
|
onClick = onSaveClick,
|
|
enabled = !uiState.isLoading,
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
if (uiState.isLoading) {
|
|
CircularProgressIndicator(modifier = Modifier.size(24.dp))
|
|
} else {
|
|
Text("Сохранить")
|
|
}
|
|
}
|
|
if (uiState.isSaved) {
|
|
Text("Настройки сохранены!", color = MaterialTheme.colorScheme.primary)
|
|
}
|
|
if (uiState.error != null) {
|
|
Text(uiState.error, color = MaterialTheme.colorScheme.error)
|
|
}
|
|
}
|
|
}
|
|
]]>
|
|
</CONTENT>
|
|
</ACTION>
|
|
|
|
<ACTION type="MODIFY" file_path="./app/src/main/java/com/homebox/lens/navigation/NavGraph.kt">
|
|
<DESCRIPTION>Добавить экран настроек в навигационный граф.</DESCRIPTION>
|
|
<INSERT after='composable(Screen.Search.route) { SearchScreen(navActions) }'>
|
|
<![CDATA[
|
|
composable(Screen.Settings.route) {
|
|
SettingsScreen(
|
|
onNavigateUp = { navActions.navController.navigateUp() }
|
|
)
|
|
}
|
|
]]>
|
|
</INSERT>
|
|
</ACTION>
|
|
|
|
<ACTION type="MODIFY" file_path="./app/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt">
|
|
<DESCRIPTION>Добавить пункт "Настройки" в боковое меню.</DESCRIPTION>
|
|
<INSERT after=' onClick = {
|
|
navActions.navController.navigate(Screen.LocationsList.route)
|
|
scope.launch { drawerState.close() }
|
|
}
|
|
)'>
|
|
<![CDATA[
|
|
NavigationDrawerItem(
|
|
icon = { Icon(Icons.Default.Settings, contentDescription = null) },
|
|
label = { Text("Настройки") },
|
|
selected = false,
|
|
onClick = {
|
|
navActions.navController.navigate(Screen.Settings.route)
|
|
scope.launch { drawerState.close() }
|
|
}
|
|
)
|
|
]]>
|
|
</INSERT>
|
|
</ACTION>
|
|
</WORK_ORDER> |