feat(settings): Replace rename-failure snackbar with dialog

This commit is contained in:
darken
2026-04-14 11:38:09 +02:00
committed by Matthias Urhahn
parent 7d08a44a19
commit 566a6cd120
2 changed files with 51 additions and 7 deletions
@@ -6,6 +6,8 @@ import androidx.compose.foundation.Canvas
import androidx.compose.foundation.clickable
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -66,13 +68,17 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
@@ -115,6 +121,7 @@ fun DeviceSettingsScreenHost(
val context = LocalContext.current
val snackbarHostState = remember { SnackbarHostState() }
var showRenameUnavailableDialog by rememberSaveable { mutableStateOf(false) }
LaunchedEffect(Unit) {
vm.events.collect { event ->
when (event) {
@@ -127,15 +134,22 @@ fun DeviceSettingsScreenHost(
)
}
DeviceSettingsViewModel.Event.SystemRenameUnavailable -> {
snackbarHostState.showSnackbar(
context.getString(R.string.device_settings_rename_system_unavailable),
duration = androidx.compose.material3.SnackbarDuration.Long,
)
showRenameUnavailableDialog = true
}
}
}
}
if (showRenameUnavailableDialog) {
SystemRenameUnavailableDialog(
onOpenBluetoothSettings = {
showRenameUnavailableDialog = false
context.startActivity(Intent(Settings.ACTION_BLUETOOTH_SETTINGS))
},
onDismiss = { showRenameUnavailableDialog = false },
)
}
val state by vm.state.collectAsStateWithLifecycle(initialValue = null)
val currentState = state ?: return
@@ -1222,6 +1236,7 @@ private fun RenameDialog(
onDismiss: () -> Unit,
) {
var textValue by remember { mutableStateOf(currentName) }
val focusRequester = remember { FocusRequester() }
// The decoder in DefaultAapDeviceProfile only round-trips printable ASCII (0x20..0x7E),
// so even if the device accepts a UTF-8 name we can't display it back correctly. Accept any
@@ -1229,6 +1244,9 @@ private fun RenameDialog(
// understands why Rename is disabled.
val hasInvalidAscii = textValue.any { it.code !in 0x20..0x7E }
val isValid = textValue.isNotBlank() && !hasInvalidAscii
val canConfirm = isValid && textValue != currentName
LaunchedEffect(Unit) { focusRequester.requestFocus() }
androidx.compose.material3.AlertDialog(
onDismissRequest = onDismiss,
@@ -1248,13 +1266,15 @@ private fun RenameDialog(
supportingText = if (hasInvalidAscii) {
{ Text(stringResource(R.string.device_settings_rename_invalid_ascii)) }
} else null,
modifier = Modifier.fillMaxWidth(),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = { if (canConfirm) onConfirm(textValue) }),
modifier = Modifier.fillMaxWidth().focusRequester(focusRequester),
)
},
confirmButton = {
androidx.compose.material3.TextButton(
onClick = { if (isValid) onConfirm(textValue) },
enabled = isValid && textValue != currentName,
onClick = { if (canConfirm) onConfirm(textValue) },
enabled = canConfirm,
) {
Text(stringResource(R.string.device_settings_rename_confirm))
}
@@ -1267,6 +1287,28 @@ private fun RenameDialog(
)
}
@Composable
private fun SystemRenameUnavailableDialog(
onOpenBluetoothSettings: () -> Unit,
onDismiss: () -> Unit,
) {
AlertDialog(
onDismissRequest = onDismiss,
title = { Text(stringResource(R.string.device_settings_rename_system_unavailable_title)) },
text = { Text(stringResource(R.string.device_settings_rename_system_unavailable)) },
confirmButton = {
TextButton(onClick = onOpenBluetoothSettings) {
Text(stringResource(R.string.device_settings_rename_system_unavailable_bt_settings_action))
}
},
dismissButton = {
TextButton(onClick = onDismiss) {
Text(stringResource(android.R.string.ok))
}
},
)
}
@Composable
private fun NoiseControlCombined(
currentMode: AapSetting.AncMode.Value,
+2
View File
@@ -500,7 +500,9 @@
<string name="device_settings_rename_hint">Device name</string>
<string name="device_settings_rename_confirm">Rename</string>
<string name="device_settings_rename_invalid_ascii">Only ASCII characters are supported</string>
<string name="device_settings_rename_system_unavailable_title">Rename incomplete</string>
<string name="device_settings_rename_system_unavailable">Android didn\'t let us rename the device here. To update the name in Bluetooth settings, rename it there or re-pair the device.</string>
<string name="device_settings_rename_system_unavailable_bt_settings_action">Bluetooth Settings</string>
<string name="device_settings_send_failed">Could not apply setting: %1$s</string>
<string name="device_settings_category_connections_label">Connected Devices</string>
<string name="device_settings_connected_devices_description">Other devices currently connected to these AirPods</string>