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.