kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
make MutableLiveData private
rodzic
25a67ec4b3
commit
8bde3d2ba4
|
@ -417,7 +417,7 @@ class MainActivity : BaseActivity(), Logging,
|
|||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
|
||||
val prefs = UIViewModel.getPreferences(this)
|
||||
model.ownerName.value = prefs.getString("owner", "")!!
|
||||
model.setOwner(prefs.getString("owner", ""))
|
||||
|
||||
/// Set theme
|
||||
setUITheme(prefs)
|
||||
|
@ -605,24 +605,6 @@ class MainActivity : BaseActivity(), Logging,
|
|||
}
|
||||
}
|
||||
|
||||
/// Pull our latest node db from the device
|
||||
private fun updateNodesFromDevice() {
|
||||
model.meshService?.let { service ->
|
||||
// Update our nodeinfos based on data from the device
|
||||
val nodes = service.nodes.associateBy { it.user?.id!! }
|
||||
model.nodeDB.nodes.value = nodes
|
||||
|
||||
try {
|
||||
// Pull down our real node ID - This must be done AFTER reading the nodedb because we need the DB to find our nodeinof object
|
||||
model.nodeDB.myId.value = service.myId
|
||||
val ourNodeInfo = model.nodeDB.ourNodeInfo
|
||||
model.ownerName.value = ourNodeInfo?.user?.longName
|
||||
} catch (ex: Exception) {
|
||||
warn("Ignoring failure to get myId, service is probably just uninited... ${ex.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Show an alert that may contain HTML */
|
||||
private fun showAlert(titleText: Int, messageText: Int) {
|
||||
// make links clickable per https://stackoverflow.com/a/62642807
|
||||
|
@ -646,19 +628,19 @@ class MainActivity : BaseActivity(), Logging,
|
|||
}
|
||||
|
||||
/// Called when we gain/lose a connection to our mesh radio
|
||||
private fun onMeshConnectionChanged(connected: MeshService.ConnectionState) {
|
||||
debug("connchange ${model.isConnected.value} -> $connected")
|
||||
private fun onMeshConnectionChanged(newConnection: MeshService.ConnectionState) {
|
||||
val oldConnection = model.isConnected.value!!
|
||||
debug("connchange $oldConnection -> $newConnection")
|
||||
|
||||
if (connected == MeshService.ConnectionState.CONNECTED) {
|
||||
if (newConnection == MeshService.ConnectionState.CONNECTED) {
|
||||
model.meshService?.let { service ->
|
||||
|
||||
val oldConnection = model.isConnected.value
|
||||
model.isConnected.value = connected
|
||||
model.setConnectionState(newConnection)
|
||||
|
||||
debug("Getting latest radioconfig from service")
|
||||
try {
|
||||
val info: MyNodeInfo? = service.myNodeInfo // this can be null
|
||||
model.myNodeInfo.value = info
|
||||
model.setMyNodeInfo(info)
|
||||
|
||||
if (info != null) {
|
||||
val isOld = info.minAppVersion > BuildConfig.VERSION_CODE
|
||||
|
@ -675,13 +657,11 @@ class MainActivity : BaseActivity(), Logging,
|
|||
else {
|
||||
// If our app is too old/new, we probably don't understand the new radioconfig messages, so we don't read them until here
|
||||
|
||||
model.radioConfig.value =
|
||||
RadioConfigProtos.RadioConfig.parseFrom(service.radioConfig)
|
||||
model.setRadioConfig(RadioConfigProtos.RadioConfig.parseFrom(service.radioConfig))
|
||||
|
||||
model.channels.value =
|
||||
ChannelSet(AppOnlyProtos.ChannelSet.parseFrom(service.channels))
|
||||
model.setChannels(ChannelSet(AppOnlyProtos.ChannelSet.parseFrom(service.channels)))
|
||||
|
||||
updateNodesFromDevice()
|
||||
model.updateNodesFromDevice()
|
||||
|
||||
// we have a connection to our device now, do the channel change
|
||||
perhapsChangeChannel()
|
||||
|
@ -691,7 +671,7 @@ class MainActivity : BaseActivity(), Logging,
|
|||
}
|
||||
} catch (ex: RemoteException) {
|
||||
warn("Abandoning connect $ex, because we probably just lost device connection")
|
||||
model.isConnected.value = oldConnection
|
||||
model.setConnectionState(oldConnection)
|
||||
}
|
||||
// if provideLocation enabled: Start providing location (from phone GPS) to mesh
|
||||
if (model.provideLocation.value == true)
|
||||
|
@ -699,7 +679,7 @@ class MainActivity : BaseActivity(), Logging,
|
|||
}
|
||||
} else {
|
||||
// For other connection states, just slam them in
|
||||
model.isConnected.value = connected
|
||||
model.setConnectionState(newConnection)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -793,8 +773,8 @@ class MainActivity : BaseActivity(), Logging,
|
|||
|
||||
// We only care about nodes that have user info
|
||||
info.user?.id?.let {
|
||||
val newnodes = model.nodeDB.nodes.value!! + Pair(it, info)
|
||||
model.nodeDB.nodes.value = newnodes
|
||||
val nodes = model.nodeDB.nodes.value!! + Pair(it, info)
|
||||
model.nodeDB.setNodes(nodes)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -887,7 +867,7 @@ class MainActivity : BaseActivity(), Logging,
|
|||
val msgs =
|
||||
allMsgs.filter { p -> p.dataType == Portnums.PortNum.TEXT_MESSAGE_APP_VALUE }
|
||||
|
||||
model.myNodeInfo.value = service.myNodeInfo // Note: this could be NULL!
|
||||
model.setMyNodeInfo(service.myNodeInfo) // Note: this could be NULL!
|
||||
debug("Service provided ${msgs.size} messages and myNodeNum ${model.myNodeInfo.value?.myNodeNum}")
|
||||
|
||||
model.messagesState.setMessages(msgs)
|
||||
|
@ -897,15 +877,14 @@ class MainActivity : BaseActivity(), Logging,
|
|||
// if we are not connected, onMeshConnectionChange won't fetch nodes from the service
|
||||
// in that case, we do it here - because the service certainly has a better idea of node db that we have
|
||||
if (connectionState != MeshService.ConnectionState.CONNECTED)
|
||||
updateNodesFromDevice()
|
||||
model.updateNodesFromDevice()
|
||||
|
||||
// We won't receive a notify for the initial state of connection, so we force an update here
|
||||
onMeshConnectionChanged(connectionState)
|
||||
} catch (ex: RemoteException) {
|
||||
// If we get an exception while reading our service config, the device might have gone away, double check to see if we are really connected
|
||||
errormsg("Device error during init ${ex.message}")
|
||||
model.isConnected.value =
|
||||
MeshService.ConnectionState.valueOf(service.connectionState())
|
||||
model.setConnectionState(MeshService.ConnectionState.valueOf(service.connectionState()))
|
||||
} finally {
|
||||
connectionJob = null
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.geeksville.mesh.model
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.geeksville.mesh.MeshProtos
|
||||
import com.geeksville.mesh.MeshUser
|
||||
|
@ -26,7 +27,7 @@ class NodeDB(private val ui: UIViewModel) {
|
|||
null
|
||||
)
|
||||
|
||||
val testNodes = testPositions.mapIndexed { index, it ->
|
||||
private val testNodes = testPositions.mapIndexed { index, it ->
|
||||
NodeInfo(
|
||||
9 + index,
|
||||
MeshUser(
|
||||
|
@ -42,13 +43,21 @@ class NodeDB(private val ui: UIViewModel) {
|
|||
private val seedWithTestNodes = false
|
||||
|
||||
/// The unique ID of our node
|
||||
val myId = object : MutableLiveData<String?>(if (seedWithTestNodes) "+16508765309" else null) {}
|
||||
private val _myId = MutableLiveData<String?>(if (seedWithTestNodes) "+16508765309" else null)
|
||||
val myId: LiveData<String?> get() = _myId
|
||||
|
||||
fun setMyId(myId: String?) {
|
||||
_myId.value = myId
|
||||
}
|
||||
|
||||
/// A map from nodeid to to nodeinfo
|
||||
val nodes =
|
||||
object :
|
||||
MutableLiveData<Map<String, NodeInfo>>(mapOf(*(if (seedWithTestNodes) testNodes else listOf()).map { it.user!!.id to it }
|
||||
.toTypedArray())) {}
|
||||
private val _nodes = MutableLiveData<Map<String, NodeInfo>>(mapOf(*(if (seedWithTestNodes) testNodes else listOf()).map { it.user!!.id to it }
|
||||
.toTypedArray()))
|
||||
val nodes: LiveData<Map<String, NodeInfo>> get() = _nodes
|
||||
|
||||
fun setNodes(nodes: Map<String, NodeInfo>) {
|
||||
_nodes.value = nodes
|
||||
}
|
||||
|
||||
/// Could be null if we haven't received our node DB yet
|
||||
val ourNodeInfo get() = nodes.value?.get(myId.value)
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.net.Uri
|
|||
import android.os.RemoteException
|
||||
import android.view.Menu
|
||||
import androidx.core.content.edit
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
|
@ -89,22 +90,26 @@ class UIViewModel @Inject constructor(
|
|||
val nodeDB = NodeDB(this)
|
||||
val messagesState = MessagesState(this)
|
||||
|
||||
/// Are we connected to our radio device
|
||||
val isConnected =
|
||||
object :
|
||||
MutableLiveData<MeshService.ConnectionState>(MeshService.ConnectionState.DISCONNECTED) {
|
||||
}
|
||||
/// Connection state to our radio device
|
||||
private val _connectionState = MutableLiveData(MeshService.ConnectionState.DISCONNECTED)
|
||||
val isConnected: LiveData<MeshService.ConnectionState> get() = _connectionState
|
||||
|
||||
// fun isConnected() = _connectionState.value == MeshService.ConnectionState.CONNECTED
|
||||
|
||||
fun setConnectionState(connectionState: MeshService.ConnectionState) {
|
||||
_connectionState.value = connectionState
|
||||
}
|
||||
|
||||
/// various radio settings (including the channel)
|
||||
val radioConfig = object : MutableLiveData<RadioConfigProtos.RadioConfig?>(null) {
|
||||
}
|
||||
private val _radioConfig = MutableLiveData<RadioConfigProtos.RadioConfig?>()
|
||||
val radioConfig: LiveData<RadioConfigProtos.RadioConfig?> get() = _radioConfig
|
||||
|
||||
val channels = object : MutableLiveData<ChannelSet?>(null) {
|
||||
}
|
||||
private val _channels = MutableLiveData<ChannelSet?>()
|
||||
val channels: LiveData<ChannelSet?> get() = _channels
|
||||
|
||||
var positionBroadcastSecs: Int?
|
||||
get() {
|
||||
radioConfig.value?.preferences?.let {
|
||||
_radioConfig.value?.preferences?.let {
|
||||
if (it.positionBroadcastSecs > 0) return it.positionBroadcastSecs
|
||||
// These default values are borrowed from the device code.
|
||||
return 15 * 60
|
||||
|
@ -112,7 +117,7 @@ class UIViewModel @Inject constructor(
|
|||
return null
|
||||
}
|
||||
set(value) {
|
||||
val config = radioConfig.value
|
||||
val config = _radioConfig.value
|
||||
if (value != null && config != null) {
|
||||
val builder = config.toBuilder()
|
||||
builder.preferencesBuilder.positionBroadcastSecs = value
|
||||
|
@ -121,9 +126,9 @@ class UIViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
var lsSleepSecs: Int?
|
||||
get() = radioConfig.value?.preferences?.lsSecs
|
||||
get() = _radioConfig.value?.preferences?.lsSecs
|
||||
set(value) {
|
||||
val config = radioConfig.value
|
||||
val config = _radioConfig.value
|
||||
if (value != null && config != null) {
|
||||
val builder = config.toBuilder()
|
||||
builder.preferencesBuilder.lsSecs = value
|
||||
|
@ -132,9 +137,9 @@ class UIViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
var locationShareDisabled: Boolean
|
||||
get() = radioConfig.value?.preferences?.locationShareDisabled ?: false
|
||||
get() = _radioConfig.value?.preferences?.locationShareDisabled ?: false
|
||||
set(value) {
|
||||
val config = radioConfig.value
|
||||
val config = _radioConfig.value
|
||||
if (config != null) {
|
||||
val builder = config.toBuilder()
|
||||
builder.preferencesBuilder.locationShareDisabled = value
|
||||
|
@ -143,9 +148,9 @@ class UIViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
var isPowerSaving: Boolean?
|
||||
get() = radioConfig.value?.preferences?.isPowerSaving
|
||||
get() = _radioConfig.value?.preferences?.isPowerSaving
|
||||
set(value) {
|
||||
val config = radioConfig.value
|
||||
val config = _radioConfig.value
|
||||
if (value != null && config != null) {
|
||||
val builder = config.toBuilder()
|
||||
builder.preferencesBuilder.isPowerSaving = value
|
||||
|
@ -161,24 +166,46 @@ class UIViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
/// hardware info about our local device (can be null)
|
||||
val myNodeInfo = object : MutableLiveData<MyNodeInfo?>(null) {}
|
||||
private val _myNodeInfo = MutableLiveData<MyNodeInfo?>()
|
||||
val myNodeInfo: LiveData<MyNodeInfo?> get() = _myNodeInfo
|
||||
|
||||
fun setMyNodeInfo(info: MyNodeInfo?) {
|
||||
_myNodeInfo.value = info
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
debug("ViewModel cleared")
|
||||
}
|
||||
|
||||
/// Pull our latest node db from the device
|
||||
fun updateNodesFromDevice() {
|
||||
meshService?.let { service ->
|
||||
// Update our nodeinfos based on data from the device
|
||||
val nodes = service.nodes.associateBy { it.user?.id!! }
|
||||
nodeDB.setNodes(nodes)
|
||||
|
||||
try {
|
||||
// Pull down our real node ID - This must be done AFTER reading the nodedb because we need the DB to find our nodeinof object
|
||||
nodeDB.setMyId(service.myId)
|
||||
val ownerName = nodeDB.ourNodeInfo?.user?.longName
|
||||
_ownerName.value = ownerName
|
||||
} catch (ex: Exception) {
|
||||
warn("Ignoring failure to get myId, service is probably just uninited... ${ex.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the primary channel info
|
||||
*/
|
||||
val primaryChannel: Channel? get() = channels.value?.primaryChannel
|
||||
val primaryChannel: Channel? get() = _channels.value?.primaryChannel
|
||||
|
||||
///
|
||||
// Set the radio config (also updates our saved copy in preferences)
|
||||
private fun setRadioConfig(c: RadioConfigProtos.RadioConfig) {
|
||||
fun setRadioConfig(c: RadioConfigProtos.RadioConfig) {
|
||||
debug("Setting new radio config!")
|
||||
meshService?.radioConfig = c.toByteArray()
|
||||
radioConfig.value =
|
||||
_radioConfig.value =
|
||||
c // Must be done after calling the service, so we will will properly throw if the service failed (and therefore not cache invalid new settings)
|
||||
}
|
||||
|
||||
|
@ -186,10 +213,10 @@ class UIViewModel @Inject constructor(
|
|||
fun setChannels(c: ChannelSet) {
|
||||
debug("Setting new channels!")
|
||||
meshService?.channels = c.protobuf.toByteArray()
|
||||
channels.value =
|
||||
_channels.value =
|
||||
c // Must be done after calling the service, so we will will properly throw if the service failed (and therefore not cache invalid new settings)
|
||||
|
||||
preferences.edit(commit = true) {
|
||||
preferences.edit {
|
||||
this.putString("channel-url", c.getChannelUrl().toString())
|
||||
}
|
||||
}
|
||||
|
@ -200,14 +227,14 @@ class UIViewModel @Inject constructor(
|
|||
/// our name in hte radio
|
||||
/// Note, we generate owner initials automatically for now
|
||||
/// our activity will read this from prefs or set it to the empty string
|
||||
val ownerName = object : MutableLiveData<String>("MrIDE Test") {
|
||||
}
|
||||
private val _ownerName = MutableLiveData<String?>()
|
||||
val ownerName: LiveData<String?> get() = _ownerName
|
||||
|
||||
val provideLocation = object : MutableLiveData<Boolean>(preferences.getBoolean(MyPreferences.provideLocationKey, false)) {
|
||||
override fun setValue(value: Boolean) {
|
||||
super.setValue(value)
|
||||
|
||||
preferences.edit(commit = true) {
|
||||
preferences.edit {
|
||||
this.putBoolean(MyPreferences.provideLocationKey, value)
|
||||
}
|
||||
}
|
||||
|
@ -217,21 +244,21 @@ class UIViewModel @Inject constructor(
|
|||
fun setOwner(s: String? = null) {
|
||||
|
||||
if (s != null) {
|
||||
ownerName.value = s
|
||||
_ownerName.value = s
|
||||
|
||||
// note: we allow an empty userstring to be written to prefs
|
||||
preferences.edit(commit = true) {
|
||||
preferences.edit {
|
||||
putString("owner", s)
|
||||
}
|
||||
}
|
||||
|
||||
// Note: we are careful to not set a new unique ID
|
||||
if (ownerName.value!!.isNotEmpty())
|
||||
if (_ownerName.value!!.isNotEmpty())
|
||||
try {
|
||||
meshService?.setOwner(
|
||||
null,
|
||||
ownerName.value,
|
||||
getInitials(ownerName.value!!)
|
||||
_ownerName.value,
|
||||
getInitials(_ownerName.value!!)
|
||||
) // Note: we use ?. here because we might be running in the emulator
|
||||
} catch (ex: RemoteException) {
|
||||
errormsg("Can't set username on device, is device offline? ${ex.message}")
|
||||
|
|
|
@ -568,7 +568,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
binding.provideLocationCheckbox.visibility = if (isConnected) View.VISIBLE else View.GONE
|
||||
|
||||
if (connected == MeshService.ConnectionState.DISCONNECTED)
|
||||
model.ownerName.value = ""
|
||||
model.setOwner("")
|
||||
|
||||
// update the region selection from the device
|
||||
val region = model.region
|
||||
|
|
Ładowanie…
Reference in New Issue