mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-07-03 01:45:36 -04:00
feat(settings): wire is_unmessagable/is_licensed into DeviceProfile export/import (#6065)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -159,6 +159,8 @@ open class RadioConfigRepositoryImpl(
|
||||
channel_url = channels.getChannelUrl().toString(),
|
||||
config = localConfig,
|
||||
module_config = localModuleConfig,
|
||||
is_unmessagable = node?.user?.is_unmessagable,
|
||||
is_licensed = node?.user?.is_licensed,
|
||||
fixed_position =
|
||||
if (node != null && localConfig.position?.fixed_position == true) {
|
||||
node.position
|
||||
|
||||
@@ -46,13 +46,17 @@ open class InstallProfileUseCase constructor(private val radioController: RadioC
|
||||
}
|
||||
}
|
||||
|
||||
// is_licensed is deliberately not installed here: enabling ham mode is a dedicated onboarding flow
|
||||
// (set_ham_mode — rewrites the owner, disables encryption, applies tx power/frequency) that a plain
|
||||
// set_owner would bypass, leaving the radio flagged licensed without those required side effects.
|
||||
private suspend fun AdminEditScope.installOwner(profile: DeviceProfile, currentUser: User?) {
|
||||
if (profile.long_name != null || profile.short_name != null) {
|
||||
if (profile.long_name != null || profile.short_name != null || profile.is_unmessagable != null) {
|
||||
currentUser?.let {
|
||||
setOwner(
|
||||
it.copy(
|
||||
long_name = profile.long_name ?: it.long_name,
|
||||
short_name = profile.short_name ?: it.short_name,
|
||||
is_unmessagable = profile.is_unmessagable ?: it.is_unmessagable,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.meshtastic.proto.ModuleConfig.TelemetryConfig
|
||||
import org.meshtastic.proto.User
|
||||
import kotlin.test.BeforeTest
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class InstallProfileUseCaseTest {
|
||||
@@ -107,4 +108,14 @@ class InstallProfileUseCaseTest {
|
||||
|
||||
assertTrue(radioController.editSettingsCalled)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `invoke installs is_unmessagable but never auto-installs is_licensed`() = runTest {
|
||||
val profile = DeviceProfile(is_unmessagable = true, is_licensed = true)
|
||||
|
||||
useCase(1234, profile, User(long_name = "Old"))
|
||||
|
||||
assertEquals(true, radioController.lastSetOwnerUser?.is_unmessagable)
|
||||
assertEquals(false, radioController.lastSetOwnerUser?.is_licensed)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ class FakeRadioController :
|
||||
|
||||
var throwOnSend: Boolean = false
|
||||
var lastSetDeviceAddress: String? = null
|
||||
var lastSetOwnerUser: User? = null
|
||||
var editSettingsCalled = false
|
||||
var startProvideLocationCalled = false
|
||||
var stopProvideLocationCalled = false
|
||||
@@ -67,6 +68,7 @@ class FakeRadioController :
|
||||
localConfigs.clear()
|
||||
throwOnSend = false
|
||||
lastSetDeviceAddress = null
|
||||
lastSetOwnerUser = null
|
||||
editSettingsCalled = false
|
||||
startProvideLocationCalled = false
|
||||
stopProvideLocationCalled = false
|
||||
@@ -107,7 +109,9 @@ class FakeRadioController :
|
||||
|
||||
override suspend fun setLocalChannel(channel: Channel) {}
|
||||
|
||||
override suspend fun setOwner(destNum: Int, user: User, packetId: Int) {}
|
||||
override suspend fun setOwner(destNum: Int, user: User, packetId: Int) {
|
||||
lastSetOwnerUser = user
|
||||
}
|
||||
|
||||
override suspend fun setHamMode(destNum: Int, hamParameters: HamParameters, packetId: Int) {}
|
||||
|
||||
|
||||
@@ -31,15 +31,20 @@ import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.cancel
|
||||
import org.meshtastic.core.resources.channel_url
|
||||
import org.meshtastic.core.resources.fixed_position
|
||||
import org.meshtastic.core.resources.licensed_amateur_radio
|
||||
import org.meshtastic.core.resources.long_name
|
||||
import org.meshtastic.core.resources.module_settings
|
||||
import org.meshtastic.core.resources.radio_configuration
|
||||
import org.meshtastic.core.resources.save
|
||||
import org.meshtastic.core.resources.short_name
|
||||
import org.meshtastic.core.resources.unmessageable
|
||||
import org.meshtastic.core.ui.component.MeshtasticDialog
|
||||
import org.meshtastic.core.ui.component.SwitchPreference
|
||||
import org.meshtastic.proto.DeviceProfile
|
||||
|
||||
private const val UNMESSAGABLE_TAG = 9
|
||||
private const val LICENSED_TAG = 10
|
||||
|
||||
private enum class ProfileField(val tag: Int, val labelRes: StringResource) {
|
||||
LONG_NAME(1, Res.string.long_name),
|
||||
SHORT_NAME(2, Res.string.short_name),
|
||||
@@ -47,6 +52,8 @@ private enum class ProfileField(val tag: Int, val labelRes: StringResource) {
|
||||
CONFIG(4, Res.string.radio_configuration),
|
||||
MODULE_CONFIG(5, Res.string.module_settings),
|
||||
FIXED_POSITION(6, Res.string.fixed_position),
|
||||
UNMESSAGABLE(UNMESSAGABLE_TAG, Res.string.unmessageable),
|
||||
LICENSED(LICENSED_TAG, Res.string.licensed_amateur_radio),
|
||||
}
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
@@ -69,6 +76,8 @@ fun EditDeviceProfileDialog(
|
||||
ProfileField.CONFIG -> deviceProfile.config != null
|
||||
ProfileField.MODULE_CONFIG -> deviceProfile.module_config != null
|
||||
ProfileField.FIXED_POSITION -> deviceProfile.fixed_position != null
|
||||
ProfileField.UNMESSAGABLE -> deviceProfile.is_unmessagable != null
|
||||
ProfileField.LICENSED -> deviceProfile.is_licensed != null
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -99,6 +108,9 @@ fun EditDeviceProfileDialog(
|
||||
} else {
|
||||
null
|
||||
},
|
||||
is_unmessagable =
|
||||
if (state[ProfileField.UNMESSAGABLE] == true) deviceProfile.is_unmessagable else null,
|
||||
is_licensed = if (state[ProfileField.LICENSED] == true) deviceProfile.is_licensed else null,
|
||||
)
|
||||
onConfirm(result)
|
||||
},
|
||||
@@ -115,6 +127,8 @@ fun EditDeviceProfileDialog(
|
||||
ProfileField.CONFIG -> deviceProfile.config != null
|
||||
ProfileField.MODULE_CONFIG -> deviceProfile.module_config != null
|
||||
ProfileField.FIXED_POSITION -> deviceProfile.fixed_position != null
|
||||
ProfileField.UNMESSAGABLE -> deviceProfile.is_unmessagable != null
|
||||
ProfileField.LICENSED -> deviceProfile.is_licensed != null
|
||||
}
|
||||
SwitchPreference(
|
||||
title = stringResource(field.labelRes),
|
||||
|
||||
Reference in New Issue
Block a user