diff --git a/app/src/main/java/com/geeksville/mesh/ui/sharing/Channel.kt b/app/src/main/java/com/geeksville/mesh/ui/sharing/Channel.kt index cdd83ede5..79e070200 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/sharing/Channel.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/sharing/Channel.kt @@ -96,7 +96,6 @@ import kotlinx.coroutines.launch import org.jetbrains.compose.resources.stringResource import org.meshtastic.core.model.Channel import org.meshtastic.core.model.util.getChannelUrl -import org.meshtastic.core.model.util.hasDuplicateKeys import org.meshtastic.core.model.util.qrCode import org.meshtastic.core.model.util.toChannelSet import org.meshtastic.core.navigation.Route @@ -108,7 +107,6 @@ import org.meshtastic.core.strings.are_you_sure_change_default import org.meshtastic.core.strings.cancel import org.meshtastic.core.strings.cant_change_no_radio import org.meshtastic.core.strings.channel_invalid -import org.meshtastic.core.strings.channel_key_already_in_use import org.meshtastic.core.strings.copy import org.meshtastic.core.strings.edit import org.meshtastic.core.strings.modem_preset @@ -233,12 +231,6 @@ fun ChannelScreen( // Send new channel settings to the device fun installSettings(newChannelSet: ChannelSet) { - // Check for duplicate keys before installing - if (newChannelSet.hasDuplicateKeys()) { - scope.launch { context.showToast(Res.string.channel_key_already_in_use) } - return - } - // Try to change the radio, if it fails, tell the user why and throw away their edits try { viewModel.setChannels(newChannelSet) diff --git a/core/model/src/main/kotlin/org/meshtastic/core/model/util/ChannelSet.kt b/core/model/src/main/kotlin/org/meshtastic/core/model/util/ChannelSet.kt index 90db14a74..757fefc3e 100644 --- a/core/model/src/main/kotlin/org/meshtastic/core/model/util/ChannelSet.kt +++ b/core/model/src/main/kotlin/org/meshtastic/core/model/util/ChannelSet.kt @@ -89,21 +89,3 @@ fun ChannelSet.qrCode(shouldAdd: Boolean): Bitmap? = try { Timber.e("URL was too complex to render as barcode") null } - -/** - * Check if the ChannelSet contains any duplicate PSKs. - * - * @return true if there are duplicate PSKs, false otherwise - */ -fun ChannelSet.hasDuplicateKeys(): Boolean { - val pskList = mutableListOf() - for (setting in settingsList) { - val channel = Channel(setting, loraConfig) - val pskBytes = channel.psk.toByteArray() - if (pskList.any { it contentEquals pskBytes }) { - return true - } - pskList.add(pskBytes) - } - return false -} diff --git a/core/strings/src/commonMain/composeResources/values/strings.xml b/core/strings/src/commonMain/composeResources/values/strings.xml index 4db966f8a..a79af3186 100644 --- a/core/strings/src/commonMain/composeResources/values/strings.xml +++ b/core/strings/src/commonMain/composeResources/values/strings.xml @@ -218,7 +218,6 @@ Service notifications About This Channel URL is invalid and can not be used - A channel with this key is already in use This contact is invalid and can not be added Debug Panel Decoded Payload: diff --git a/core/ui/src/main/kotlin/org/meshtastic/core/ui/qr/ScannedQrCodeDialog.kt b/core/ui/src/main/kotlin/org/meshtastic/core/ui/qr/ScannedQrCodeDialog.kt index 02d2b471b..ae715e339 100644 --- a/core/ui/src/main/kotlin/org/meshtastic/core/ui/qr/ScannedQrCodeDialog.kt +++ b/core/ui/src/main/kotlin/org/meshtastic/core/ui/qr/ScannedQrCodeDialog.kt @@ -40,11 +40,9 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewScreenSizes import androidx.compose.ui.unit.dp @@ -52,19 +50,15 @@ import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import kotlinx.coroutines.launch import org.jetbrains.compose.resources.stringResource import org.meshtastic.core.model.Channel -import org.meshtastic.core.model.util.hasDuplicateKeys import org.meshtastic.core.strings.Res import org.meshtastic.core.strings.accept import org.meshtastic.core.strings.add import org.meshtastic.core.strings.cancel -import org.meshtastic.core.strings.channel_key_already_in_use import org.meshtastic.core.strings.new_channel_rcvd import org.meshtastic.core.strings.replace import org.meshtastic.core.ui.component.ChannelSelection -import org.meshtastic.core.ui.util.showToast import org.meshtastic.proto.AppOnlyProtos.ChannelSet import org.meshtastic.proto.ConfigProtos.Config.LoRaConfig.ModemPreset import org.meshtastic.proto.channelSet @@ -296,16 +290,10 @@ fun ScannedQrCodeDialog( ) } - val context = LocalContext.current - val coroutineScope = rememberCoroutineScope() TextButton( onClick = { - if (selectedChannelSet.hasDuplicateKeys()) { - coroutineScope.launch { context.showToast(Res.string.channel_key_already_in_use) } - } else { - onDismiss() - onConfirm(selectedChannelSet) - } + onDismiss() + onConfirm(selectedChannelSet) }, enabled = selectedChannelSet.settingsCount in 1..8, ) { diff --git a/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/channel/ChannelConfigScreen.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/channel/ChannelConfigScreen.kt index addad471c..1e20496fc 100644 --- a/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/channel/ChannelConfigScreen.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/channel/ChannelConfigScreen.kt @@ -37,33 +37,27 @@ import androidx.compose.material3.Icon import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.listSaver import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.runtime.toMutableStateList import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.compose.collectAsStateWithLifecycle -import kotlinx.coroutines.launch import org.jetbrains.compose.resources.stringResource import org.meshtastic.core.model.Channel import org.meshtastic.core.model.DeviceVersion -import org.meshtastic.core.model.util.hasDuplicateKeys import org.meshtastic.core.strings.Res import org.meshtastic.core.strings.add import org.meshtastic.core.strings.cancel -import org.meshtastic.core.strings.channel_key_already_in_use import org.meshtastic.core.strings.channel_name import org.meshtastic.core.strings.channels import org.meshtastic.core.strings.press_and_drag @@ -73,7 +67,6 @@ import org.meshtastic.core.ui.component.PreferenceFooter import org.meshtastic.core.ui.component.dragContainer import org.meshtastic.core.ui.component.dragDropItemsIndexed import org.meshtastic.core.ui.component.rememberDragDropState -import org.meshtastic.core.ui.util.showToast import org.meshtastic.feature.settings.radio.RadioConfigViewModel import org.meshtastic.feature.settings.radio.channel.component.ChannelCard import org.meshtastic.feature.settings.radio.channel.component.ChannelConfigHeader @@ -82,7 +75,6 @@ import org.meshtastic.feature.settings.radio.channel.component.ChannelLegendDial import org.meshtastic.feature.settings.radio.channel.component.EditChannelDialog import org.meshtastic.feature.settings.radio.channel.component.SECONDARY_CHANNEL_EPOCH import org.meshtastic.feature.settings.radio.component.PacketResponseStateDialog -import org.meshtastic.proto.AppOnlyProtos import org.meshtastic.proto.ChannelProtos.ChannelSettings import org.meshtastic.proto.ConfigProtos.Config.LoRaConfig import org.meshtastic.proto.channelSettings @@ -143,69 +135,21 @@ private fun ChannelConfigScreen( settingsList.size != settingsListInput.size || settingsList.zip(settingsListInput).any { (item1, item2) -> item1 != item2 } - // Check if the current channel list has duplicate PSKs - recompute when list changes - var hasDuplicateKeys by remember { mutableStateOf(false) } - LaunchedEffect(settingsListInput.size, settingsListInput.toList(), loraConfig) { - val channelSet = - AppOnlyProtos.ChannelSet.newBuilder() - .apply { - addAllSettings(settingsListInput.toList()) - setLoraConfig(loraConfig) - } - .build() - hasDuplicateKeys = channelSet.hasDuplicateKeys() - } - var showEditChannelDialog: Int? by rememberSaveable { mutableStateOf(null) } var showChannelLegendDialog by rememberSaveable { mutableStateOf(false) } - val context = LocalContext.current - val coroutineScope = rememberCoroutineScope() - if (showEditChannelDialog != null) { val index = showEditChannelDialog ?: return EditChannelDialog( channelSettings = with(settingsListInput) { if (size > index) get(index) else channelSettings {} }, modemPresetName = modemPresetName, - onAddClick = { newChannelSettings -> - val isEditing = index < settingsListInput.size - - // Build a temporary list to check for duplicates - val tempList = settingsListInput.toMutableList() - if (isEditing) { - tempList[index] = newChannelSettings + onAddClick = { + if (settingsListInput.size > index) { + settingsListInput[index] = it } else { - tempList.add(newChannelSettings) - } - - // Check for duplicates in the temporary list - val tempChannelSet = - AppOnlyProtos.ChannelSet.newBuilder() - .apply { - addAllSettings(tempList) - setLoraConfig(loraConfig) - } - .build() - - val hasDuplicate = tempChannelSet.hasDuplicateKeys() - - if (hasDuplicate) { - coroutineScope.launch { context.showToast(Res.string.channel_key_already_in_use) } - // If this was a new channel added by FAB (at the end), remove it - // FAB adds channel then opens dialog, so index will be lastIndex - if (index == settingsListInput.size - 1 && index >= 0) { - settingsListInput.removeAt(index) - showEditChannelDialog = null - } - // If editing existing channel, don't update - keep original and dialog open - } else { - if (isEditing) { - settingsListInput[index] = newChannelSettings - } else { - settingsListInput.add(newChannelSettings) - } - showEditChannelDialog = null + settingsListInput.add(it) } + showEditChannelDialog = null }, onDismissRequest = { showEditChannelDialog = null }, ) @@ -294,7 +238,7 @@ private fun ChannelConfigScreen( item { Spacer(modifier = Modifier.weight(1f)) } item { PreferenceFooter( - enabled = enabled && isEditing && !hasDuplicateKeys, + enabled = enabled && isEditing, negativeText = stringResource(Res.string.cancel), onNegativeClicked = { focusManager.clearFocus() @@ -304,11 +248,7 @@ private fun ChannelConfigScreen( positiveText = stringResource(Res.string.send), onPositiveClicked = { focusManager.clearFocus() - if (hasDuplicateKeys) { - coroutineScope.launch { context.showToast(Res.string.channel_key_already_in_use) } - } else { - onPositiveClicked(settingsListInput) - } + onPositiveClicked(settingsListInput) }, ) }