sforkowany z mirror/meshtastic-android
fix: ensure proper channel updates to `ChannelSetRepository`
rodzic
a2388d1d12
commit
8151aceea4
|
@ -15,6 +15,7 @@ import androidx.lifecycle.asLiveData
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.geeksville.mesh.android.Logging
|
import com.geeksville.mesh.android.Logging
|
||||||
import com.geeksville.mesh.*
|
import com.geeksville.mesh.*
|
||||||
|
import com.geeksville.mesh.ChannelProtos.ChannelSettings
|
||||||
import com.geeksville.mesh.ClientOnlyProtos.DeviceProfile
|
import com.geeksville.mesh.ClientOnlyProtos.DeviceProfile
|
||||||
import com.geeksville.mesh.ConfigProtos.Config
|
import com.geeksville.mesh.ConfigProtos.Config
|
||||||
import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig
|
import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig
|
||||||
|
@ -56,7 +57,6 @@ import java.io.InputStream
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/// Given a human name, strip out the first letter of the first three words and return that as the initials for
|
/// Given a human name, strip out the first letter of the first three words and return that as the initials for
|
||||||
|
@ -85,7 +85,7 @@ fun getInitials(nameIn: String): String {
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class UIViewModel @Inject constructor(
|
class UIViewModel @Inject constructor(
|
||||||
private val app: Application,
|
private val app: Application,
|
||||||
radioConfigRepository: RadioConfigRepository,
|
private val radioConfigRepository: RadioConfigRepository,
|
||||||
private val meshLogRepository: MeshLogRepository,
|
private val meshLogRepository: MeshLogRepository,
|
||||||
private val packetRepository: PacketRepository,
|
private val packetRepository: PacketRepository,
|
||||||
private val quickChatActionRepository: QuickChatActionRepository,
|
private val quickChatActionRepository: QuickChatActionRepository,
|
||||||
|
@ -451,23 +451,51 @@ class UIViewModel @Inject constructor(
|
||||||
setModuleConfig(myNodeNum ?: return, config)
|
setModuleConfig(myNodeNum ?: return, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the channels array to and from [AppOnlyProtos.ChannelSet]
|
/**
|
||||||
private var _channelSet: AppOnlyProtos.ChannelSet
|
* Updates channels to match the [new] list. Only channels with changes are updated.
|
||||||
get() = channels.value.protobuf
|
*
|
||||||
set(value) {
|
* @param destNum Destination node number.
|
||||||
(0 until max(_channelSet.settingsCount, value.settingsCount)).map { i ->
|
* @param old The current [ChannelSettings] list.
|
||||||
channel {
|
* @param new The updated [ChannelSettings] list.
|
||||||
|
*/
|
||||||
|
fun updateChannels(
|
||||||
|
destNum: Int,
|
||||||
|
old: List<ChannelSettings>,
|
||||||
|
new: List<ChannelSettings>,
|
||||||
|
) {
|
||||||
|
buildList {
|
||||||
|
for (i in 0..maxOf(old.lastIndex, new.lastIndex)) {
|
||||||
|
if (old.getOrNull(i) != new.getOrNull(i)) add(channel {
|
||||||
role = when (i) {
|
role = when (i) {
|
||||||
0 -> ChannelProtos.Channel.Role.PRIMARY
|
0 -> ChannelProtos.Channel.Role.PRIMARY
|
||||||
in 1 until value.settingsCount -> ChannelProtos.Channel.Role.SECONDARY
|
in 1..new.lastIndex -> ChannelProtos.Channel.Role.SECONDARY
|
||||||
else -> ChannelProtos.Channel.Role.DISABLED
|
else -> ChannelProtos.Channel.Role.DISABLED
|
||||||
}
|
}
|
||||||
index = i
|
index = i
|
||||||
settings = value.settingsList.getOrNull(i) ?: channelSettings { }
|
settings = new.getOrNull(i) ?: channelSettings { }
|
||||||
}
|
})
|
||||||
}.forEach {
|
|
||||||
meshService?.setChannel(it.toByteArray())
|
|
||||||
}
|
}
|
||||||
|
}.forEach { setRemoteChannel(destNum, it) }
|
||||||
|
|
||||||
|
if (destNum == myNodeNum) viewModelScope.launch {
|
||||||
|
radioConfigRepository.replaceAllSettings(new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateChannels(
|
||||||
|
old: List<ChannelSettings>,
|
||||||
|
new: List<ChannelSettings>
|
||||||
|
) {
|
||||||
|
updateChannels(myNodeNum ?: return, old, new)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the [channels] array to and from [ChannelSet]
|
||||||
|
*/
|
||||||
|
private var _channelSet: AppOnlyProtos.ChannelSet
|
||||||
|
get() = channels.value.protobuf
|
||||||
|
set(value) {
|
||||||
|
updateChannels(channelSet.settingsList, value.settingsList)
|
||||||
|
|
||||||
val newConfig = config { lora = value.loraConfig }
|
val newConfig = config { lora = value.loraConfig }
|
||||||
if (config.lora != newConfig.lora) setConfig(newConfig)
|
if (config.lora != newConfig.lora) setConfig(newConfig)
|
||||||
|
@ -476,12 +504,16 @@ class UIViewModel @Inject constructor(
|
||||||
|
|
||||||
/// Set the radio config (also updates our saved copy in preferences)
|
/// Set the radio config (also updates our saved copy in preferences)
|
||||||
fun setChannels(channelSet: ChannelSet) {
|
fun setChannels(channelSet: ChannelSet) {
|
||||||
debug("Setting new channels!")
|
|
||||||
this._channelSet = channelSet.protobuf
|
this._channelSet = channelSet.protobuf
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setRemoteChannel(destNum: Int, channel: ChannelProtos.Channel) {
|
private fun setRemoteChannel(destNum: Int, channel: ChannelProtos.Channel) {
|
||||||
meshService?.setRemoteChannel(destNum, channel.toByteArray())
|
try {
|
||||||
|
debug("Sending channel ${channel.index} to $destNum")
|
||||||
|
meshService?.setRemoteChannel(destNum, channel.toByteArray())
|
||||||
|
} catch (ex: RemoteException) {
|
||||||
|
errormsg("Can't set channel on radio ${ex.message}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// our name in hte radio
|
/// our name in hte radio
|
||||||
|
|
|
@ -35,6 +35,18 @@ class ChannelSetRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun clearSettings() {
|
||||||
|
channelSetStore.updateData { preference ->
|
||||||
|
preference.toBuilder().clearSettings().build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun addAllSettings(settingsList: List<ChannelSettings>) {
|
||||||
|
channelSetStore.updateData { preference ->
|
||||||
|
preference.toBuilder().addAllSettings(settingsList).build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the [ChannelSettings] list with the provided channel and returns the index of the
|
* Updates the [ChannelSettings] list with the provided channel and returns the index of the
|
||||||
* admin channel after the update (if not found, returns 0).
|
* admin channel after the update (if not found, returns 0).
|
||||||
|
@ -42,11 +54,7 @@ class ChannelSetRepository @Inject constructor(
|
||||||
suspend fun updateChannelSettings(channel: Channel): Int {
|
suspend fun updateChannelSettings(channel: Channel): Int {
|
||||||
channelSetStore.updateData { preference ->
|
channelSetStore.updateData { preference ->
|
||||||
if (preference.settingsCount > channel.index) {
|
if (preference.settingsCount > channel.index) {
|
||||||
if (channel.role == Channel.Role.DISABLED) {
|
preference.toBuilder().setSettings(channel.index, channel.settings).build()
|
||||||
preference.toBuilder().removeSettings(channel.index).build()
|
|
||||||
} else {
|
|
||||||
preference.toBuilder().setSettings(channel.index, channel.settings).build()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
preference.toBuilder().addSettings(channel.settings).build()
|
preference.toBuilder().addSettings(channel.settings).build()
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,14 @@ class RadioConfigRepository @Inject constructor(
|
||||||
channelSetRepository.clearChannelSet()
|
channelSetRepository.clearChannelSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the [ChannelSettings] list with a new [settingsList].
|
||||||
|
*/
|
||||||
|
suspend fun replaceAllSettings(settingsList: List<ChannelSettings>) {
|
||||||
|
channelSetRepository.clearSettings()
|
||||||
|
channelSetRepository.addAllSettings(settingsList)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the [ChannelSettings] list with the provided channel and returns the index of the
|
* Updates the [ChannelSettings] list with the provided channel and returns the index of the
|
||||||
* admin channel after the update (if not found, returns 0).
|
* admin channel after the update (if not found, returns 0).
|
||||||
|
|
|
@ -1715,7 +1715,6 @@ class MeshService : Service(), Logging {
|
||||||
override fun setRemoteChannel(destNum: Int, payload: ByteArray?) = toRemoteExceptions {
|
override fun setRemoteChannel(destNum: Int, payload: ByteArray?) = toRemoteExceptions {
|
||||||
val channel = ChannelProtos.Channel.parseFrom(payload)
|
val channel = ChannelProtos.Channel.parseFrom(payload)
|
||||||
sendToRadio(newMeshPacketTo(destNum).buildAdminPacket { setChannel = channel })
|
sendToRadio(newMeshPacketTo(destNum).buildAdminPacket { setChannel = channel })
|
||||||
if (destNum == myNodeNum) updateChannelSettings(channel) // Update our local copy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRemoteChannel(id: Int, destNum: Int, index: Int) = toRemoteExceptions {
|
override fun getRemoteChannel(id: Int, destNum: Int, index: Int) = toRemoteExceptions {
|
||||||
|
|
|
@ -67,8 +67,6 @@ import com.geeksville.mesh.NodeInfo
|
||||||
import com.geeksville.mesh.Portnums
|
import com.geeksville.mesh.Portnums
|
||||||
import com.geeksville.mesh.R
|
import com.geeksville.mesh.R
|
||||||
import com.geeksville.mesh.android.Logging
|
import com.geeksville.mesh.android.Logging
|
||||||
import com.geeksville.mesh.channel
|
|
||||||
import com.geeksville.mesh.channelSettings
|
|
||||||
import com.geeksville.mesh.config
|
import com.geeksville.mesh.config
|
||||||
import com.geeksville.mesh.deviceProfile
|
import com.geeksville.mesh.deviceProfile
|
||||||
import com.geeksville.mesh.model.UIViewModel
|
import com.geeksville.mesh.model.UIViewModel
|
||||||
|
@ -391,20 +389,7 @@ fun RadioConfigNavHost(node: NodeInfo, viewModel: UIViewModel = viewModel()) {
|
||||||
focusManager = focusManager,
|
focusManager = focusManager,
|
||||||
onSaveClicked = { channelListInput ->
|
onSaveClicked = { channelListInput ->
|
||||||
focusManager.clearFocus()
|
focusManager.clearFocus()
|
||||||
(0 until channelList.size.coerceAtLeast(channelListInput.size)).map { i ->
|
viewModel.updateChannels(destNum, channelList, channelListInput)
|
||||||
channel {
|
|
||||||
role = when (i) {
|
|
||||||
0 -> ChannelProtos.Channel.Role.PRIMARY
|
|
||||||
in 1 until channelListInput.size -> ChannelProtos.Channel.Role.SECONDARY
|
|
||||||
else -> ChannelProtos.Channel.Role.DISABLED
|
|
||||||
}
|
|
||||||
index = i
|
|
||||||
settings = channelListInput.getOrNull(i) ?: channelSettings { }
|
|
||||||
}
|
|
||||||
}.forEach { newChannel ->
|
|
||||||
if (newChannel.settings != channelList.getOrNull(newChannel.index))
|
|
||||||
viewModel.setRemoteChannel(destNum, newChannel)
|
|
||||||
}
|
|
||||||
channelList.clear()
|
channelList.clear()
|
||||||
channelList.addAll(channelListInput)
|
channelList.addAll(channelListInput)
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue