From 8551234cfbf379f210aee019c0b125b9f430b6de Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 28 Oct 2026 12:39:39 +0100 Subject: [PATCH] Show unknown battery exemption state with an explicit retry action --- .../components/BatteryOptimizationSetting.kt | 29 ++++++++++++++----- .../app/src/main/res/values-ru/strings.xml | 1 + .../app/src/main/res/values/strings.xml | 1 + 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/BatteryOptimizationSetting.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/BatteryOptimizationSetting.kt index 63e2c2ae..5713783b 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/BatteryOptimizationSetting.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/BatteryOptimizationSetting.kt @@ -19,6 +19,11 @@ import androidx.lifecycle.compose.LifecycleResumeEffect import com.utun.chat.data.BatteryOptimizationPermission import com.utun.chat.data.LogManager +/** Исключение из оптимизации батареи: источник истины — PowerManager, повторная проверка выполняется на каждом RESUME. + * null означает ошибку чтения, а не отказ пользователя: показываем диагностику/«Повторить» без запуска системного запроса. + * «Разрешить» ещё раз проверяет ОС и открывает запрос только при известном false; pending сохраняется при пересоздании UI. + * Возврат из системного экрана снимает pending и читает состояние заново, resultCode не используется. + * enabled блокирует только кнопку; настройка не останавливает ядро и не блокирует завершение первоначальной настройки. */ @Composable fun BatteryOptimizationSetting(source: String, enabled: Boolean = true) { val context = LocalContext.current @@ -31,14 +36,16 @@ fun BatteryOptimizationSetting(source: String, enabled: Boolean = true) { LifecycleResumeEffect(context, source) { granted = BatteryOptimizationPermission.granted(context) if (lastLoggedState != granted) { - LogManager.addLog("INFO", "PERMISSION", "Battery optimization exemption: source=$source granted=$granted") + LogManager.addLog(if (granted == null) "ERROR" else "INFO", "PERMISSION", + "Battery optimization exemption: source=$source granted=$granted") lastLoggedState = granted } if (requestPending) { - LogManager.addLog(if (granted) "INFO" else "WARN", "PERMISSION", "Battery optimization request completed: source=$source granted=$granted") + val level = when (granted) { true -> "INFO"; false -> "WARN"; null -> "ERROR" } + LogManager.addLog(level, "PERMISSION", "Battery optimization request completed: source=$source granted=$granted") requestPending = false } - if (granted) error = null + if (granted == true) error = null onPauseOrDispose { } } @@ -47,20 +54,26 @@ fun BatteryOptimizationSetting(source: String, enabled: Boolean = true) { Text(stringResource(R.string.background_unrestricted), style = MaterialTheme.typography.titleMedium) Text(stringResource(R.string.battery_optimization_hint), style = MaterialTheme.typography.bodySmall) - Text(stringResource(if (granted) R.string.allowed else R.string.not_allowed), style = MaterialTheme.typography.bodyMedium, - color = if (granted) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant) - if (!granted) { + Text(stringResource(when (granted) { + true -> R.string.allowed; false -> R.string.not_allowed; null -> R.string.battery_state_failed + }), style = MaterialTheme.typography.bodyMedium, color = when (granted) { + true -> MaterialTheme.colorScheme.primary + false -> MaterialTheme.colorScheme.onSurfaceVariant + null -> MaterialTheme.colorScheme.error + }) + if (granted != true) { Button(enabled = enabled && !requestPending, onClick = { error = null + val retryQuery = granted == null granted = BatteryOptimizationPermission.granted(context) - if (!granted) { + if (granted == false && !retryQuery) { requestPending = true if (!BatteryOptimizationPermission.request(context, source)) { requestPending = false error = R.string.battery_settings_failed } } - }) { Text(stringResource(R.string.grant)) } + }) { Text(stringResource(if (granted == null) R.string.retry else R.string.grant)) } } error?.let { Text(stringResource(it), color = MaterialTheme.colorScheme.error, style = MaterialTheme.typography.bodySmall) } } diff --git a/tools/chatgui-android/app/src/main/res/values-ru/strings.xml b/tools/chatgui-android/app/src/main/res/values-ru/strings.xml index c49f1727..e768fb53 100644 --- a/tools/chatgui-android/app/src/main/res/values-ru/strings.xml +++ b/tools/chatgui-android/app/src/main/res/values-ru/strings.xml @@ -407,6 +407,7 @@ "Разрешите работу без оптимизации батареи для получения сообщений и звонков в фоне. Это может увеличить расход батареи." "Не разрешено" "Не удалось открыть настройки батареи. Разрешите работу без ограничений в системных настройках приложения." + Не удалось проверить исключение из оптимизации батареи. Повторите проверку. "В сети" "Не в сети" "Подготовка медиа…" diff --git a/tools/chatgui-android/app/src/main/res/values/strings.xml b/tools/chatgui-android/app/src/main/res/values/strings.xml index 116f48f3..ebc15032 100644 --- a/tools/chatgui-android/app/src/main/res/values/strings.xml +++ b/tools/chatgui-android/app/src/main/res/values/strings.xml @@ -408,6 +408,7 @@ "Allow unrestricted battery use to receive messages and calls in the background. This may increase battery consumption." "Not allowed" "Could not open battery settings. Allow unrestricted battery use in the app’s system settings." + Could not check the battery optimization exemption. Retry the check. "Online" "Offline" "Preparing media…"