mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2026-01-22 16:14:23 +01:00
Add first working example of CGM service in new approach
This commit is contained in:
@@ -8,6 +8,7 @@ import no.nordicsemi.android.hrs.view.HRSScreen
|
||||
import no.nordicsemi.android.hts.view.HTSScreen
|
||||
import no.nordicsemi.android.navigation.ComposeDestination
|
||||
import no.nordicsemi.android.navigation.ComposeDestinations
|
||||
import no.nordicsemi.android.nrftoolbox.view.HomeScreen
|
||||
import no.nordicsemi.android.prx.view.PRXScreen
|
||||
import no.nordicsemi.android.rscs.view.RSCSScreen
|
||||
import no.nordicsemi.android.uart.view.UARTScreen
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package no.nordicsemi.android.nrftoolbox
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import no.nordicsemi.android.navigation.NavigationManager
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class HomeViewModel @Inject constructor(
|
||||
private val navigationManager: NavigationManager
|
||||
) : ViewModel() {
|
||||
|
||||
fun openProfile(destination: ProfileDestination) {
|
||||
navigationManager.navigateTo(destination.destination.id)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package no.nordicsemi.android.nrftoolbox
|
||||
package no.nordicsemi.android.nrftoolbox.view
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
@@ -6,19 +6,25 @@ import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import no.nordicsemi.android.nrftoolbox.R
|
||||
import no.nordicsemi.android.theme.view.ScreenSection
|
||||
|
||||
@Composable
|
||||
@@ -26,6 +32,7 @@ fun FeatureButton(
|
||||
@DrawableRes iconId: Int,
|
||||
@StringRes nameCode: Int,
|
||||
@StringRes name: Int,
|
||||
isRunning: Boolean? = null,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
ScreenSection(onClick = onClick) {
|
||||
@@ -57,15 +64,32 @@ fun FeatureButton(
|
||||
|
||||
Spacer(modifier = Modifier.size(16.dp))
|
||||
|
||||
Text(
|
||||
text = stringResource(id = nameCode),
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
// Text(
|
||||
// text = stringResource(id = nameCode),
|
||||
// style = MaterialTheme.typography.headlineSmall,
|
||||
// textAlign = TextAlign.Center
|
||||
// )
|
||||
|
||||
isRunning?.let {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_running_indicator),
|
||||
contentDescription = stringResource(id = R.string.running_profile_icon),
|
||||
tint = getRunningIndicatorColor(it)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getRunningIndicatorColor(isRunning: Boolean): Color {
|
||||
return if (isRunning) {
|
||||
colorResource(id = R.color.nordicGrass)
|
||||
} else {
|
||||
MaterialTheme.colorScheme.outline
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun FeatureButtonPreview() {
|
||||
@@ -1,4 +1,4 @@
|
||||
package no.nordicsemi.android.nrftoolbox
|
||||
package no.nordicsemi.android.nrftoolbox.view
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
@@ -6,17 +6,23 @@ import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import no.nordicsemi.android.nrftoolbox.BuildConfig
|
||||
import no.nordicsemi.android.nrftoolbox.ProfileDestination
|
||||
import no.nordicsemi.android.nrftoolbox.R
|
||||
import no.nordicsemi.android.nrftoolbox.viewmodel.HomeViewModel
|
||||
import no.nordicsemi.android.theme.view.TitleAppBar
|
||||
|
||||
@Composable
|
||||
fun HomeScreen() {
|
||||
val viewModel: HomeViewModel = hiltViewModel()
|
||||
val state = viewModel.state.collectAsState().value
|
||||
|
||||
Column {
|
||||
TitleAppBar(stringResource(id = R.string.app_name))
|
||||
@@ -34,21 +40,15 @@ fun HomeScreen() {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Text(
|
||||
text = stringResource(id = R.string.bluetooth_services),
|
||||
text = stringResource(id = R.string.viewmodel_profiles),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
FeatureButton(R.drawable.ic_csc, R.string.csc_module, R.string.csc_module_full) {
|
||||
viewModel.openProfile(ProfileDestination.CSC)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
FeatureButton(R.drawable.ic_hrs, R.string.hrs_module, R.string.hrs_module_full) {
|
||||
viewModel.openProfile(ProfileDestination.HRS)
|
||||
FeatureButton(R.drawable.ic_bps, R.string.bps_module, R.string.bps_module_full) {
|
||||
viewModel.openProfile(ProfileDestination.BPS)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
@@ -59,31 +59,45 @@ fun HomeScreen() {
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
FeatureButton(R.drawable.ic_hts, R.string.hts_module, R.string.hts_module_full) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.service_profiles),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
FeatureButton(R.drawable.ic_csc, R.string.csc_module, R.string.csc_module_full, state.isCSCModuleRunning) {
|
||||
viewModel.openProfile(ProfileDestination.CSC)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
FeatureButton(R.drawable.ic_hrs, R.string.hrs_module, R.string.hrs_module_full, state.isHRSModuleRunning) {
|
||||
viewModel.openProfile(ProfileDestination.HRS)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
FeatureButton(R.drawable.ic_hts, R.string.hts_module, R.string.hts_module_full, state.isHTSModuleRunning) {
|
||||
viewModel.openProfile(ProfileDestination.HTS)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
FeatureButton(R.drawable.ic_bps, R.string.bps_module, R.string.bps_module_full) {
|
||||
viewModel.openProfile(ProfileDestination.BPS)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
FeatureButton(R.drawable.ic_rscs, R.string.rscs_module, R.string.rscs_module_full) {
|
||||
FeatureButton(R.drawable.ic_rscs, R.string.rscs_module, R.string.rscs_module_full, state.isRSCSModuleRunning) {
|
||||
viewModel.openProfile(ProfileDestination.RSCS)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
FeatureButton(R.drawable.ic_prx, R.string.prx_module, R.string.prx_module_full) {
|
||||
FeatureButton(R.drawable.ic_prx, R.string.prx_module, R.string.prx_module_full, state.isPRXModuleRunning) {
|
||||
viewModel.openProfile(ProfileDestination.PRX)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
FeatureButton(R.drawable.ic_cgm, R.string.cgm_module, R.string.cgm_module_full) {
|
||||
FeatureButton(R.drawable.ic_cgm, R.string.cgm_module, R.string.cgm_module_full, state.isCGMModuleRunning) {
|
||||
viewModel.openProfile(ProfileDestination.CGMS)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package no.nordicsemi.android.nrftoolbox.view
|
||||
|
||||
data class HomeViewState(
|
||||
val isCSCModuleRunning: Boolean = false,
|
||||
val isHRSModuleRunning: Boolean = false,
|
||||
val isHTSModuleRunning: Boolean = false,
|
||||
val isRSCSModuleRunning: Boolean = false,
|
||||
val isPRXModuleRunning: Boolean = false,
|
||||
val isCGMModuleRunning: Boolean = false
|
||||
)
|
||||
@@ -0,0 +1,34 @@
|
||||
package no.nordicsemi.android.nrftoolbox.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import no.nordicsemi.android.cgms.data.CGMRepository
|
||||
import no.nordicsemi.android.navigation.NavigationManager
|
||||
import no.nordicsemi.android.nrftoolbox.ProfileDestination
|
||||
import no.nordicsemi.android.nrftoolbox.view.HomeViewState
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class HomeViewModel @Inject constructor(
|
||||
private val navigationManager: NavigationManager,
|
||||
private val cgmRepository: CGMRepository
|
||||
) : ViewModel() {
|
||||
|
||||
private val _state = MutableStateFlow(HomeViewState())
|
||||
val state = _state.asStateFlow()
|
||||
|
||||
init {
|
||||
cgmRepository.isRunning.onEach {
|
||||
_state.value = _state.value.copy(isCGMModuleRunning = it)
|
||||
}.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
fun openProfile(destination: ProfileDestination) {
|
||||
navigationManager.navigateTo(destination.destination.id)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user