refactor: convert connectionState to StateFlow

This commit is contained in:
andrekir
2024-11-12 09:08:08 -03:00
parent a980441fd1
commit cfdb245da2
8 changed files with 25 additions and 42 deletions

View File

@@ -27,6 +27,7 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.asLiveData
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.geeksville.mesh.android.*
import com.geeksville.mesh.concurrent.handledLaunch
@@ -541,7 +542,7 @@ class MainActivity : AppCompatActivity(), Logging {
override fun onStart() {
super.onStart()
model.connectionState.observe(this) { state ->
model.connectionState.asLiveData().observe(this) { state ->
onMeshConnectionChanged(state)
updateConnectionStatusImage(state)
}
@@ -619,7 +620,7 @@ class MainActivity : AppCompatActivity(), Logging {
menuInflater.inflate(R.menu.menu_main, menu)
model.actionBarMenu = menu
updateConnectionStatusImage(model.connectionState.value!!)
updateConnectionStatusImage(model.connectionState.value)
return true
}

View File

@@ -465,7 +465,7 @@ class UIViewModel @Inject constructor(
}
// Connection state to our radio device
val connectionState get() = radioConfigRepository.connectionState.asLiveData()
val connectionState get() = radioConfigRepository.connectionState
fun isConnected() = connectionState.value != MeshService.ConnectionState.DISCONNECTED
private val _requestChannelUrl = MutableLiveData<Uri?>(null)

View File

@@ -140,6 +140,7 @@ class MeshService : Service(), Logging {
DEVICE_SLEEP, // device is in LS sleep state, it will reconnected to us over bluetooth once it has data
;
fun isConnected() = this == CONNECTED
fun isDisconnected() = this == DISCONNECTED
}

View File

@@ -17,6 +17,7 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.ContentAlpha
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
@@ -29,11 +30,9 @@ import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.twotone.Check
import androidx.compose.material.icons.twotone.Close
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.icons.twotone.ContentCopy
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -63,14 +62,14 @@ import androidx.fragment.app.activityViewModels
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.geeksville.mesh.AppOnlyProtos.ChannelSet
import com.geeksville.mesh.analytics.DataPair
import com.geeksville.mesh.android.GeeksvilleApplication
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.ChannelProtos
import com.geeksville.mesh.ConfigProtos
import com.geeksville.mesh.R
import com.geeksville.mesh.analytics.DataPair
import com.geeksville.mesh.android.BuildUtils.debug
import com.geeksville.mesh.android.BuildUtils.errormsg
import com.geeksville.mesh.android.GeeksvilleApplication
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.android.getCameraPermissions
import com.geeksville.mesh.android.hasCameraPermission
import com.geeksville.mesh.channelSet
@@ -129,7 +128,7 @@ fun ChannelScreen(
val focusManager = LocalFocusManager.current
val clipboardManager = LocalClipboardManager.current
val connectionState by viewModel.connectionState.observeAsState()
val connectionState by viewModel.connectionState.collectAsStateWithLifecycle()
val enabled = connectionState == MeshService.ConnectionState.CONNECTED && !viewModel.isManaged
val channels by viewModel.channels.collectAsStateWithLifecycle()

View File

@@ -161,7 +161,7 @@ class MessagesFragment : Fragment(), Logging {
}
// If connection state _OR_ myID changes we have to fix our ability to edit outgoing messages
model.connectionState.observe(viewLifecycleOwner) {
model.connectionState.asLiveData().observe(viewLifecycleOwner) {
// If we don't know our node ID and we are offline don't let user try to send
val isConnected = model.isConnected()
binding.textInputLayout.isEnabled = isConnected

View File

@@ -1,9 +1,3 @@
@file:Suppress(
"LongMethod",
"MagicNumber",
"CyclomaticComplexMethod",
)
package com.geeksville.mesh.ui
import androidx.compose.animation.animateColorAsState
@@ -58,8 +52,6 @@ import com.geeksville.mesh.ConfigProtos.Config.DisplayConfig
import com.geeksville.mesh.MeshProtos
import com.geeksville.mesh.R
import com.geeksville.mesh.database.entity.NodeEntity
import com.geeksville.mesh.service.MeshService
import com.geeksville.mesh.service.MeshService.ConnectionState
import com.geeksville.mesh.ui.components.MenuItemAction
import com.geeksville.mesh.ui.components.NodeKeyStatusIcon
import com.geeksville.mesh.ui.components.NodeMenu
@@ -71,6 +63,7 @@ import com.geeksville.mesh.ui.theme.AppTheme
import com.geeksville.mesh.util.metersIn
import com.geeksville.mesh.util.toDistanceString
@Suppress("LongMethod", "CyclomaticComplexMethod")
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun NodeItem(
@@ -84,10 +77,9 @@ fun NodeItem(
blinking: Boolean = false,
expanded: Boolean = false,
currentTimeMillis: Long,
connectionState: MeshService.ConnectionState? = ConnectionState.DISCONNECTED,
isConnected: Boolean = false,
) {
val isUnknownUser = thatNode.isUnknownUser
val unknownShortName = stringResource(id = R.string.unknown_node_short_name)
val isIgnored = ignoreIncomingList.contains(thatNode.num)
val longName = thatNode.user.longName.ifEmpty { stringResource(id = R.string.unknown_username) }
val isThisNode = thisNode?.num == thatNode.num
@@ -101,28 +93,23 @@ fun NodeItem(
MeshProtos.HardwareModel.UNSET -> MeshProtos.HardwareModel.UNSET.name
else -> hwModel.name.replace('_', '-').replace('p', '.').lowercase()
}
val roleName = if (isUnknownUser) {
val roleName = if (thatNode.isUnknownUser) {
DeviceConfig.Role.UNRECOGNIZED.name
} else {
thatNode.user.role.name
}
val nodeId = thatNode.user.id.ifEmpty { "???" }
val highlight = Color(0x33FFFFFF)
val bgColor by animateColorAsState(
targetValue = if (blinking) highlight else Color.Transparent,
targetValue = if (blinking) Color(color = 0x33FFFFFF) else Color.Transparent,
animationSpec = repeatable(
iterations = 6,
animation = tween(
durationMillis = 250,
easing = FastOutSlowInEasing
),
animation = tween(durationMillis = 250, easing = FastOutSlowInEasing),
repeatMode = RepeatMode.Reverse
),
label = "blinking node"
)
val style = if (isUnknownUser) {
val style = if (thatNode.isUnknownUser) {
LocalTextStyle.current.copy(fontStyle = FontStyle.Italic)
} else {
LocalTextStyle.current
@@ -179,7 +166,7 @@ fun NodeItem(
content = {
Text(
modifier = Modifier.fillMaxWidth(),
text = thatNode.user.shortName.ifEmpty { unknownShortName },
text = thatNode.user.shortName.ifEmpty { "???" },
fontWeight = FontWeight.Normal,
fontSize = MaterialTheme.typography.button.fontSize,
textDecoration = TextDecoration.LineThrough.takeIf {
@@ -196,7 +183,7 @@ fun NodeItem(
onMenuItemAction = menuItemActionClicked,
expanded = menuExpanded,
onDismissRequest = { menuExpanded = false },
isConnected = connectionState == ConnectionState.CONNECTED,
isConnected = isConnected,
)
}
NodeKeyStatusIcon(
@@ -208,11 +195,7 @@ fun NodeItem(
modifier = Modifier.weight(1f),
text = longName,
style = style,
textDecoration = TextDecoration.LineThrough.takeIf {
ignoreIncomingList.contains(
thatNode.num
)
},
textDecoration = TextDecoration.LineThrough.takeIf { isIgnored },
softWrap = true,
)
@@ -322,7 +305,7 @@ fun NodeItem(
)
Text(
modifier = Modifier.weight(1f),
text = nodeId,
text = thatNode.user.id.ifEmpty { "???" },
textAlign = TextAlign.End,
fontSize = MaterialTheme.typography.button.fontSize,
style = style,

View File

@@ -183,7 +183,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
}
// Only let user edit their name or set software update while connected to a radio
model.connectionState.observe(viewLifecycleOwner) {
model.connectionState.asLiveData().observe(viewLifecycleOwner) {
updateNodeInfo()
}

View File

@@ -14,7 +14,6 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
@@ -96,7 +95,7 @@ fun NodesScreen(
}
val currentTimeMillis = rememberTimeTickWithLifecycle()
val connectionState by model.connectionState.observeAsState()
val connectionState by model.connectionState.collectAsStateWithLifecycle()
LazyColumn(
state = listState,
@@ -140,7 +139,7 @@ fun NodesScreen(
blinking = node == focusedNode,
expanded = state.showDetails,
currentTimeMillis = currentTimeMillis,
connectionState = connectionState,
isConnected = connectionState.isConnected(),
)
}
}