From 2859bed4162be8a5152511e256c7745a820d4322 Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Wed, 5 Mar 2025 07:26:19 -0600 Subject: [PATCH] feat #1611: Add confirmation dialog when changing to router role (#1636) * Add confirmation dialog for changing to router role Introduced a confirmation dialog that will be shown when changing the device role to "router". The confirmation dialog includes links to the "Device Role Documentation" and "Choosing The Right Device Role" blog post. The user must check a checkbox to confirm. * Update router role handling Modified the handling of the router role in `DeviceConfigItemList.kt` to avoid returning prematurely from the `onItemSelected` lambda. This ensures that the role is updated properly when a user selects the "ROUTER" role. * removes konami code check, remove testing code * Refactor router role confirmation text - Moves the router role confirmation text to strings.xml. - Updates to use `AnnotatedString.fromHtml` instead of `buildAnnotatedString` and `withLink`. - Changes from hard-coded strings to string resources. --- .../components/DeviceConfigItemList.kt | 81 ++++++++++++++++++- app/src/main/res/values/strings.xml | 3 + 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DeviceConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DeviceConfigItemList.kt index 0d3c16c4..9b08ae7f 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DeviceConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DeviceConfigItemList.kt @@ -17,19 +17,31 @@ package com.geeksville.mesh.ui.radioconfig.components +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.AlertDialog +import androidx.compose.material.Checkbox import androidx.compose.material.Divider +import androidx.compose.material.Text +import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf 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.graphics.Color import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextLinkStyles +import androidx.compose.ui.text.fromHtml import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview @@ -97,6 +109,57 @@ fun DeviceConfigScreen( ) } +@Suppress("LongMethod") +@Composable +fun RouterRoleConfirmationDialog( + onDismiss: () -> Unit, + onConfirm: () -> Unit, +) { + val dialogTitle = stringResource(R.string.are_you_sure) + val annotatedDialogText = AnnotatedString.fromHtml( + htmlString = stringResource(R.string.router_role_confirmation_text), + linkStyles = TextLinkStyles(style = SpanStyle(color = Color.Blue)) + ) + + var confirmed by rememberSaveable { mutableStateOf(false) } + + AlertDialog( + title = { + Text(text = dialogTitle) + }, + text = { + Column { + Text(text = annotatedDialogText) + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Checkbox( + checked = confirmed, + onCheckedChange = { confirmed = it } + ) + Text(stringResource(R.string.i_know_what_i_m_doing)) + } + } + }, + onDismissRequest = onDismiss, + confirmButton = { + TextButton( + onClick = onConfirm, + enabled = confirmed + ) { + Text(stringResource(R.string.accept)) + } + }, + dismissButton = { + TextButton( + onClick = onDismiss + ) { + Text(stringResource(R.string.cancel)) + } + } + ) +} + @Composable fun DeviceConfigItemList( deviceConfig: DeviceConfig, @@ -106,6 +169,16 @@ fun DeviceConfigItemList( val focusManager = LocalFocusManager.current var deviceInput by rememberSaveable { mutableStateOf(deviceConfig) } + var showRouterRoleConfirmationDialog by rememberSaveable { mutableStateOf(false) } + if (showRouterRoleConfirmationDialog) { + RouterRoleConfirmationDialog( + onDismiss = { showRouterRoleConfirmationDialog = false }, + onConfirm = { + showRouterRoleConfirmationDialog = false + deviceInput = deviceInput.copy { role = DeviceConfig.Role.ROUTER } + } + ) + } LazyColumn( modifier = Modifier.fillMaxSize() ) { @@ -116,7 +189,13 @@ fun DeviceConfigItemList( title = "Role", enabled = enabled, selectedItem = deviceInput.role, - onItemSelected = { deviceInput = deviceInput.copy { role = it } }, + onItemSelected = { + if (it == DeviceConfig.Role.ROUTER && deviceInput.role != DeviceConfig.Role.ROUTER) { + showRouterRoleConfirmationDialog = true + } else { + deviceInput = deviceInput.copy { role = it } + } + }, summary = stringResource(id = deviceInput.role.stringRes), ) Divider() diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 36d8f31b..6364a680 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -328,4 +328,7 @@ Channel 3 Current Voltage + Are you sure? + Device Role Documentation and the blog post about Choosing The Right Device Role.]]> + I know what I\'m doing.