mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
fix: Multiple bugs - settings text fields, dropdowns, missing override duty cycle, and MQTT icon display (#3833)
This commit is contained in:
parent
9bc1b87e75
commit
1c3784235e
9 changed files with 58 additions and 55 deletions
|
|
@ -721,6 +721,7 @@ class MeshService : Service() {
|
|||
rssi = packet.rxRssi,
|
||||
replyId = data.replyId,
|
||||
relayNode = packet.relayNode,
|
||||
viaMqtt = packet.viaMqtt,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ data class PacketEntity(
|
|||
packetId = packetId,
|
||||
emojis = reactions.toReaction(getNode),
|
||||
replyId = data.replyId,
|
||||
viaMqtt = node.viaMqtt,
|
||||
viaMqtt = data.viaMqtt,
|
||||
relayNode = data.relayNode,
|
||||
relays = data.relays,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ data class DataPacket(
|
|||
var replyId: Int? = null, // If this is a reply to a previous message, this is the ID of that message
|
||||
var relayNode: Int? = null,
|
||||
var relays: Int = 0,
|
||||
var viaMqtt: Boolean = false, // True if this packet passed via MQTT somewhere along its path
|
||||
) : Parcelable {
|
||||
|
||||
/** If there was an error with this message, this string describes what was wrong. */
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ fun EditTextPreference(
|
|||
onValueChanged: (Double) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
summary: String? = null,
|
||||
onFocusChanged: (FocusState) -> Unit = {},
|
||||
) {
|
||||
var valueState by remember(value) { mutableStateOf(value.toString()) }
|
||||
val decimalSeparators = setOf('.', ',', '٫', '、', '·') // set of possible decimal separators
|
||||
|
|
@ -185,7 +186,7 @@ fun EditTextPreference(
|
|||
}
|
||||
}
|
||||
},
|
||||
onFocusChanged = {},
|
||||
onFocusChanged = onFocusChanged,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ fun CannedMessageConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(),
|
|||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
onDismissPacketResponse = viewModel::clearPacketResponse,
|
||||
additionalDirtyCheck = { messagesInput != messages },
|
||||
onDiscard = { messagesInput = messages },
|
||||
onSave = {
|
||||
if (messagesInput != messages) {
|
||||
viewModel.setCannedMessages(messagesInput)
|
||||
|
|
|
|||
|
|
@ -130,6 +130,8 @@ fun ExternalNotificationConfigScreen(
|
|||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
onDismissPacketResponse = viewModel::clearPacketResponse,
|
||||
additionalDirtyCheck = { ringtoneInput != ringtone },
|
||||
onDiscard = { ringtoneInput = ringtone },
|
||||
onSave = {
|
||||
if (ringtoneInput != ringtone) {
|
||||
viewModel.setRingtone(ringtoneInput)
|
||||
|
|
@ -259,7 +261,7 @@ fun ExternalNotificationConfigScreen(
|
|||
DropDownPreference(
|
||||
title = stringResource(Res.string.output_duration_milliseconds),
|
||||
items = outputItems.map { it.value to it.toDisplayString() },
|
||||
selectedItem = formState.value.outputMs,
|
||||
selectedItem = formState.value.outputMs.toLong(),
|
||||
enabled = state.connected,
|
||||
onItemSelected = { formState.value = formState.value.copy { outputMs = it.toInt() } },
|
||||
)
|
||||
|
|
@ -268,7 +270,7 @@ fun ExternalNotificationConfigScreen(
|
|||
DropDownPreference(
|
||||
title = stringResource(Res.string.nag_timeout_seconds),
|
||||
items = nagItems.map { it.value to it.toDisplayString() },
|
||||
selectedItem = formState.value.nagTimeout,
|
||||
selectedItem = formState.value.nagTimeout.toLong(),
|
||||
enabled = state.connected,
|
||||
onItemSelected = { formState.value = formState.value.copy { nagTimeout = it.toInt() } },
|
||||
)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ import org.meshtastic.core.strings.lora
|
|||
import org.meshtastic.core.strings.modem_preset
|
||||
import org.meshtastic.core.strings.ok_to_mqtt
|
||||
import org.meshtastic.core.strings.options
|
||||
import org.meshtastic.core.strings.override_duty_cycle
|
||||
import org.meshtastic.core.strings.override_frequency_mhz
|
||||
import org.meshtastic.core.strings.pa_fan_disabled
|
||||
import org.meshtastic.core.strings.region_frequency_plan
|
||||
|
|
@ -169,6 +170,14 @@ fun LoRaConfigScreen(viewModel: RadioConfigViewModel, onBack: () -> Unit) {
|
|||
containerColor = CardDefaults.cardColors().containerColor,
|
||||
)
|
||||
HorizontalDivider()
|
||||
SwitchPreference(
|
||||
title = stringResource(Res.string.override_duty_cycle),
|
||||
checked = formState.value.overrideDutyCycle,
|
||||
enabled = state.connected,
|
||||
onCheckedChange = { formState.value = formState.value.copy { overrideDutyCycle = it } },
|
||||
containerColor = CardDefaults.cardColors().containerColor,
|
||||
)
|
||||
HorizontalDivider()
|
||||
val hopLimitItems = remember { hopLimits }
|
||||
DropDownPreference(
|
||||
title = stringResource(Res.string.hop_limit),
|
||||
|
|
|
|||
|
|
@ -149,6 +149,8 @@ fun PositionConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBa
|
|||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
onDismissPacketResponse = viewModel::clearPacketResponse,
|
||||
additionalDirtyCheck = { locationInput != currentPosition },
|
||||
onDiscard = { locationInput = currentPosition },
|
||||
onSave = {
|
||||
if (formState.value.fixedPosition) {
|
||||
if (locationInput != currentPosition) {
|
||||
|
|
@ -233,9 +235,9 @@ fun PositionConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBa
|
|||
value = locationInput.latitude,
|
||||
enabled = state.connected,
|
||||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onValueChanged = { value ->
|
||||
if (value >= -90 && value <= 90.0) {
|
||||
locationInput = locationInput.copy(latitude = value)
|
||||
onValueChanged = { lat: Double ->
|
||||
if (lat >= -90 && lat <= 90.0) {
|
||||
locationInput = locationInput.copy(latitude = lat)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
@ -245,9 +247,9 @@ fun PositionConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBa
|
|||
value = locationInput.longitude,
|
||||
enabled = state.connected,
|
||||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onValueChanged = { value ->
|
||||
if (value >= -180 && value <= 180.0) {
|
||||
locationInput = locationInput.copy(longitude = value)
|
||||
onValueChanged = { lon: Double ->
|
||||
if (lon >= -180 && lon <= 180.0) {
|
||||
locationInput = locationInput.copy(longitude = lon)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
@ -257,7 +259,7 @@ fun PositionConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBa
|
|||
value = locationInput.altitude,
|
||||
enabled = state.connected,
|
||||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onValueChanged = { value -> locationInput = locationInput.copy(altitude = value) },
|
||||
onValueChanged = { alt: Int -> locationInput = locationInput.copy(altitude = alt) },
|
||||
)
|
||||
HorizontalDivider()
|
||||
TextButton(
|
||||
|
|
|
|||
|
|
@ -22,20 +22,14 @@ import androidx.compose.animation.expandIn
|
|||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.shrinkOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -59,6 +53,8 @@ fun <T : MessageLite> RadioConfigScreenList(
|
|||
enabled: Boolean,
|
||||
onSave: (T) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
additionalDirtyCheck: () -> Boolean = { false },
|
||||
onDiscard: () -> Unit = {},
|
||||
content: LazyListScope.() -> Unit,
|
||||
) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
|
|
@ -81,48 +77,37 @@ fun <T : MessageLite> RadioConfigScreenList(
|
|||
)
|
||||
},
|
||||
) { innerPadding ->
|
||||
val showFooterButtons = configState.isDirty
|
||||
val showFooterButtons = configState.isDirty || additionalDirtyCheck()
|
||||
|
||||
Box(modifier = Modifier.padding(innerPadding)) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
content()
|
||||
LazyColumn(
|
||||
modifier = Modifier.padding(innerPadding).fillMaxSize(),
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
content()
|
||||
|
||||
item {
|
||||
AnimatedVisibility(
|
||||
visible = showFooterButtons,
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
enter = expandIn(),
|
||||
exit = shrinkOut(),
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(64.dp))
|
||||
}
|
||||
item {
|
||||
AnimatedVisibility(
|
||||
visible = showFooterButtons,
|
||||
enter = fadeIn() + expandIn(),
|
||||
exit = fadeOut() + shrinkOut(),
|
||||
) {
|
||||
PreferenceFooter(
|
||||
enabled = enabled && showFooterButtons,
|
||||
negativeText = stringResource(Res.string.discard_changes),
|
||||
onNegativeClicked = {
|
||||
focusManager.clearFocus()
|
||||
configState.reset()
|
||||
onDiscard()
|
||||
},
|
||||
positiveText = stringResource(Res.string.save_changes),
|
||||
onPositiveClicked = {
|
||||
focusManager.clearFocus()
|
||||
onSave(configState.value)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = showFooterButtons,
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
enter = fadeIn() + slideInVertically(initialOffsetY = { it }),
|
||||
exit = fadeOut() + slideOutVertically(targetOffsetY = { it }),
|
||||
) {
|
||||
PreferenceFooter(
|
||||
enabled = enabled && configState.isDirty,
|
||||
negativeText = stringResource(Res.string.discard_changes),
|
||||
onNegativeClicked = {
|
||||
focusManager.clearFocus()
|
||||
configState.reset()
|
||||
},
|
||||
positiveText = stringResource(Res.string.save_changes),
|
||||
onPositiveClicked = {
|
||||
focusManager.clearFocus()
|
||||
onSave(configState.value)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue