diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/SimpleAlertDialog.kt b/app/src/main/java/com/geeksville/mesh/ui/components/SimpleAlertDialog.kt
new file mode 100644
index 000000000..03fbde541
--- /dev/null
+++ b/app/src/main/java/com/geeksville/mesh/ui/components/SimpleAlertDialog.kt
@@ -0,0 +1,75 @@
+package com.geeksville.mesh.ui.components
+
+import androidx.annotation.StringRes
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.AlertDialog
+import androidx.compose.material.ButtonDefaults
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.material.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.PreviewLightDark
+import androidx.compose.ui.unit.dp
+import com.geeksville.mesh.R
+import com.geeksville.mesh.ui.theme.AppTheme
+
+@Composable
+fun SimpleAlertDialog(
+ @StringRes title: Int,
+ text: @Composable (() -> Unit)? = null,
+ onDismiss: () -> Unit = {},
+) = AlertDialog(
+ onDismissRequest = onDismiss,
+ confirmButton = {
+ TextButton(
+ onClick = onDismiss,
+ modifier = Modifier
+ .padding(horizontal = 16.dp),
+ colors = ButtonDefaults.textButtonColors(
+ contentColor = MaterialTheme.colors.onSurface,
+ ),
+ ) { Text(text = stringResource(id = R.string.close)) }
+ },
+ title = {
+ Text(
+ text = stringResource(id = title),
+ modifier = Modifier.fillMaxWidth(),
+ textAlign = TextAlign.Center,
+ )
+ },
+ text = text,
+ shape = RoundedCornerShape(16.dp),
+)
+
+@Composable
+fun SimpleAlertDialog(
+ @StringRes title: Int,
+ @StringRes text: Int,
+ onDismiss: () -> Unit = {},
+) = SimpleAlertDialog(
+ onDismiss = onDismiss,
+ title = title,
+ text = {
+ Text(
+ text = stringResource(id = text),
+ modifier = Modifier.fillMaxWidth(),
+ textAlign = TextAlign.Center,
+ )
+ },
+)
+
+@PreviewLightDark
+@Composable
+private fun SimpleAlertDialogPreview() {
+ AppTheme {
+ SimpleAlertDialog(
+ title = R.string.message,
+ text = R.string.sample_message,
+ )
+ }
+}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/NetworkConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/NetworkConfigItemList.kt
index 26d30f2d2..00a7ff711 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/NetworkConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/NetworkConfigItemList.kt
@@ -23,6 +23,7 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.geeksville.mesh.ConfigProtos.Config.NetworkConfig
+import com.geeksville.mesh.R
import com.geeksville.mesh.copy
import com.geeksville.mesh.ui.components.DropDownPreference
import com.geeksville.mesh.ui.components.EditIPv4Preference
@@ -30,10 +31,20 @@ import com.geeksville.mesh.ui.components.EditPasswordPreference
import com.geeksville.mesh.ui.components.EditTextPreference
import com.geeksville.mesh.ui.components.PreferenceCategory
import com.geeksville.mesh.ui.components.PreferenceFooter
+import com.geeksville.mesh.ui.components.SimpleAlertDialog
import com.geeksville.mesh.ui.components.SwitchPreference
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanOptions
+@Composable
+private fun ScanErrorDialog(
+ onDismiss: () -> Unit = {}
+) = SimpleAlertDialog(
+ title = R.string.error,
+ text = R.string.wifi_qr_code_error,
+ onDismiss = onDismiss,
+)
+
@Composable
fun NetworkConfigItemList(
networkConfig: NetworkConfig,
@@ -43,6 +54,11 @@ fun NetworkConfigItemList(
val focusManager = LocalFocusManager.current
var networkInput by rememberSaveable { mutableStateOf(networkConfig) }
+ var showScanErrorDialog: Boolean by rememberSaveable { mutableStateOf(false) }
+ if (showScanErrorDialog) {
+ ScanErrorDialog { showScanErrorDialog = false }
+ }
+
fun extractWifiCredentials(qrCode: String) = Regex("""WIFI:S:(.*?);.*?P:(.*?);""")
.find(qrCode)?.destructured
?.let { (ssid, password) -> ssid to password }
@@ -55,7 +71,7 @@ fun NetworkConfigItemList(
networkInput = networkInput.copy { wifiSsid = ssid }
networkInput = networkInput.copy { wifiPsk = psk }
} else {
- // TODO show: "Invalid WiFi Credential QR code format"
+ showScanErrorDialog = true
}
}
}
@@ -237,3 +253,9 @@ private fun NetworkConfigPreview() {
onSaveClicked = { },
)
}
+
+@Preview(showBackground = true)
+@Composable
+private fun QrCodeErrorDialogPreview() {
+ ScanErrorDialog()
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 83970e728..7c1d9d455 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -212,4 +212,6 @@
- Do you want to add %d new channels?
Replace
+ Scan WiFi QR code
+ Invalid WiFi Credential QR code format