Expose language read and selection failures in the settings UI

This commit is contained in:
evgeny committed 2026-10-28 14:43:27 +01:00
1 parent caccb4e56f
commit a541484df1
1 file changed
+45 -17
@@ -3,39 +3,67 @@ package com.utun.chat.ui.components
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import com.utun.chat.R
import com.utun.chat.data.AppLanguage
import com.utun.chat.data.LogManager
/** Выбор одного языка каталога либо «Как в системе»; название текущего запроса учитывает приоритетный список Android.
* Чтение повторяется при новой Configuration/явной попытке; ошибка не выдаётся за системный выбор.
* Неудачный select оставляет прежний выбор и показывает ошибку, повтор открывает меню без перезапуска служб.
* Успех означает принятие запроса AppCompat; фактические ресурсы/пересоздание Activity применяет Android. */
@Composable
fun LanguageSetting() {
var expanded by remember { mutableStateOf(false) }
val selected = AppLanguage.selectedTag()
var retry by remember { mutableIntStateOf(0) }
var selectionFailed by remember { mutableStateOf(false) }
val configuration = LocalConfiguration.current
val state = remember(configuration, retry) {
runCatching { AppLanguage.selectedTag() to AppLanguage.supportedTags }
}
val selection = state.getOrNull()
val selected = selection?.first
val systemLabel = stringResource(R.string.language_system)
val options = listOf("" to systemLabel) + AppLanguage.supportedTags.map { it to AppLanguage.nativeName(it) }
val selectedName = options.firstOrNull { it.first == selected }?.second ?: AppLanguage.nativeName(selected)
Box(Modifier.fillMaxWidth()) {
OutlinedButton(onClick = {
expanded = true
LogManager.addLog("DEBUG", "LANGUAGE", "Language menu opened: selected=$selected options=${options.map { it.first }}")
}, modifier = Modifier.fillMaxWidth()) {
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
Column(Modifier.weight(1f)) {
Text(stringResource(R.string.interface_language), style = MaterialTheme.typography.labelMedium)
Text(selectedName, style = MaterialTheme.typography.bodyLarge)
val options = listOf("" to systemLabel) + selection?.second.orEmpty().map { it to AppLanguage.nativeName(it) }
val selectedName = if (selected == null) stringResource(R.string.retry)
else options.firstOrNull { it.first == selected }?.second ?: AppLanguage.nativeName(selected)
Column(Modifier.fillMaxWidth()) {
Box(Modifier.fillMaxWidth()) {
OutlinedButton(onClick = {
selectionFailed = false
if (state.isFailure) {
retry++
LogManager.addLog("DEBUG", "LANGUAGE", "Language settings read retry requested")
} else {
expanded = true
LogManager.addLog("DEBUG", "LANGUAGE", "Language menu opened: selected=$selected options=${options.map { it.first }}")
}
}, modifier = Modifier.fillMaxWidth()) {
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
Column(Modifier.weight(1f)) {
Text(stringResource(R.string.interface_language), style = MaterialTheme.typography.labelMedium)
Text(selectedName, style = MaterialTheme.typography.bodyLarge)
}
Icon(if (state.isFailure) Icons.Default.Refresh else Icons.Default.ArrowDropDown, contentDescription = null)
}
Icon(Icons.Default.ArrowDropDown, contentDescription = null)
}
}
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
options.forEach { (tag, name) ->
DropdownMenuItem(text = { Text(name) }, onClick = { expanded = false; AppLanguage.select(tag) })
DropdownMenu(expanded = expanded && state.isSuccess, onDismissRequest = { expanded = false }) {
options.forEach { (tag, name) ->
DropdownMenuItem(text = { Text(name) }, onClick = {
expanded = false
selectionFailed = !AppLanguage.select(tag)
if (!selectionFailed) retry++
})
}
}
}
val error = when { state.isFailure -> R.string.language_load_failed; selectionFailed -> R.string.language_apply_failed; else -> null }
error?.let { Text(stringResource(it), color = MaterialTheme.colorScheme.error, style = MaterialTheme.typography.bodySmall) }
}
}