mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
refactor: implement repository pattern for NodeDB (#835)
- enforce Unidirectional Data Flow removing nodeDB updates via `MainActivity`/`UIState` - merge `MyNodeInfoDao` into `NodeInfoDao` - move node list re-indexing to database
This commit is contained in:
parent
3f0dfb7690
commit
c8f93db00d
10 changed files with 170 additions and 147 deletions
|
|
@ -1,100 +1,74 @@
|
|||
package com.geeksville.mesh.model
|
||||
|
||||
import com.geeksville.mesh.MeshProtos
|
||||
import com.geeksville.mesh.MeshUser
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.coroutineScope
|
||||
import com.geeksville.mesh.MyNodeInfo
|
||||
import com.geeksville.mesh.NodeInfo
|
||||
import com.geeksville.mesh.Position
|
||||
import com.geeksville.mesh.database.dao.MyNodeInfoDao
|
||||
import com.geeksville.mesh.database.dao.NodeInfoDao
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class NodeDB @Inject constructor(
|
||||
private val myNodeInfoDao: MyNodeInfoDao,
|
||||
processLifecycle: Lifecycle,
|
||||
private val nodeInfoDao: NodeInfoDao,
|
||||
) {
|
||||
|
||||
fun myNodeInfoFlow(): Flow<MyNodeInfo?> = myNodeInfoDao.getMyNodeInfo()
|
||||
private suspend fun setMyNodeInfo(myInfo: MyNodeInfo) = withContext(Dispatchers.IO) {
|
||||
myNodeInfoDao.setMyNodeInfo(myInfo)
|
||||
}
|
||||
// hardware info about our local device (can be null)
|
||||
private val _myNodeInfo = MutableStateFlow<MyNodeInfo?>(null)
|
||||
val myNodeInfo: StateFlow<MyNodeInfo?> get() = _myNodeInfo
|
||||
|
||||
fun nodeInfoFlow(): Flow<List<NodeInfo>> = nodeInfoDao.getNodes()
|
||||
suspend fun upsert(node: NodeInfo) = withContext(Dispatchers.IO) {
|
||||
nodeInfoDao.upsert(node)
|
||||
}
|
||||
|
||||
suspend fun installNodeDB(mi: MyNodeInfo, nodes: List<NodeInfo>) {
|
||||
myNodeInfoDao.clearMyNodeInfo()
|
||||
nodeInfoDao.clearNodeInfo()
|
||||
nodeInfoDao.putAll(nodes)
|
||||
setMyNodeInfo(mi) // set MyNodeInfo last
|
||||
}
|
||||
|
||||
private val testPositions = arrayOf(
|
||||
Position(32.776665, -96.796989, 35, 123), // dallas
|
||||
Position(32.960758, -96.733521, 35, 456), // richardson
|
||||
Position(32.912901, -96.781776, 35, 789), // north dallas
|
||||
)
|
||||
|
||||
private val testNodeNoPosition = NodeInfo(
|
||||
8,
|
||||
MeshUser(
|
||||
"+16508765308".format(8),
|
||||
"Kevin MesterNoLoc",
|
||||
"KLO",
|
||||
MeshProtos.HardwareModel.ANDROID_SIM,
|
||||
false
|
||||
),
|
||||
null
|
||||
)
|
||||
|
||||
private val testNodes = (listOf(testNodeNoPosition) + testPositions.mapIndexed { index, it ->
|
||||
NodeInfo(
|
||||
9 + index,
|
||||
MeshUser(
|
||||
"+165087653%02d".format(9 + index),
|
||||
"Kevin Mester$index",
|
||||
"KM$index",
|
||||
MeshProtos.HardwareModel.ANDROID_SIM,
|
||||
false
|
||||
),
|
||||
it
|
||||
)
|
||||
}).associateBy { it.user?.id!! }
|
||||
|
||||
private val seedWithTestNodes = false
|
||||
// our node info
|
||||
private val _ourNodeInfo = MutableStateFlow<NodeInfo?>(null)
|
||||
val ourNodeInfo: StateFlow<NodeInfo?> get() = _ourNodeInfo
|
||||
|
||||
// The unique userId of our node
|
||||
private val _myId = MutableStateFlow(if (seedWithTestNodes) "+16508765309" else null)
|
||||
private val _myId = MutableStateFlow<String?>(null)
|
||||
val myId: StateFlow<String?> get() = _myId
|
||||
|
||||
fun setMyId(myId: String?) {
|
||||
_myId.value = myId
|
||||
}
|
||||
|
||||
// A map from nodeNum to NodeInfo
|
||||
private val _nodeDBbyNum = MutableStateFlow<Map<Int, NodeInfo>>(mapOf())
|
||||
val nodeDBbyNum: StateFlow<Map<Int, NodeInfo>> get() = _nodeDBbyNum
|
||||
val nodesByNum get() = nodeDBbyNum.value
|
||||
|
||||
// A map from userId to NodeInfo
|
||||
private val _nodes = MutableStateFlow(if (seedWithTestNodes) testNodes else mapOf())
|
||||
val nodes: StateFlow<Map<String, NodeInfo>> get() = _nodes
|
||||
private val _nodeDBbyID = MutableStateFlow<Map<String, NodeInfo>>(mapOf())
|
||||
val nodeDBbyID: StateFlow<Map<String, NodeInfo>> get() = _nodeDBbyID
|
||||
val nodes get() = nodeDBbyID
|
||||
|
||||
fun setNodes(nodes: Map<String, NodeInfo>) {
|
||||
_nodes.value = nodes
|
||||
init {
|
||||
nodeInfoDao.getMyNodeInfo().onEach { _myNodeInfo.value = it }
|
||||
.launchIn(processLifecycle.coroutineScope)
|
||||
|
||||
nodeInfoDao.nodeDBbyNum().onEach { _nodeDBbyNum.value = it }
|
||||
.launchIn(processLifecycle.coroutineScope)
|
||||
|
||||
nodeInfoDao.nodeDBbyID().onEach { _nodeDBbyID.value = it }
|
||||
.launchIn(processLifecycle.coroutineScope)
|
||||
}
|
||||
|
||||
fun setNodes(list: List<NodeInfo>) {
|
||||
setNodes(list.associateBy { it.user?.id!! })
|
||||
_nodeDBbyNum.value = list.associateBy { it.num }
|
||||
fun myNodeInfoFlow(): Flow<MyNodeInfo?> = nodeInfoDao.getMyNodeInfo()
|
||||
fun nodeInfoFlow(): Flow<List<NodeInfo>> = nodeInfoDao.getNodes()
|
||||
suspend fun upsert(node: NodeInfo) = withContext(Dispatchers.IO) {
|
||||
nodeInfoDao.upsert(node)
|
||||
}
|
||||
|
||||
suspend fun installNodeDB(mi: MyNodeInfo, nodes: List<NodeInfo>) = withContext(Dispatchers.IO) {
|
||||
nodeInfoDao.apply {
|
||||
clearNodeInfo()
|
||||
clearMyNodeInfo()
|
||||
putAll(nodes)
|
||||
setMyNodeInfo(mi) // set MyNodeInfo last
|
||||
}
|
||||
val ourNodeInfo = nodes.find { it.num == mi.myNodeNum }
|
||||
_ourNodeInfo.value = ourNodeInfo
|
||||
_myId.value = ourNodeInfo?.user?.id
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue