make MutableLiveData private

pull/419/head
andrekir 2022-04-22 17:22:06 -03:00
rodzic 25a67ec4b3
commit 8bde3d2ba4
4 zmienionych plików z 92 dodań i 77 usunięć

Wyświetl plik

@ -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
}

Wyświetl plik

@ -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)

Wyświetl plik

@ -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}")

Wyświetl plik

@ -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