mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2025-12-22 17:04:23 +01:00
Switch to new navigation.
This commit is contained in:
@@ -71,6 +71,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation libs.nordic.ble.common
|
implementation libs.nordic.ble.common
|
||||||
implementation libs.nordic.ui.scanner
|
implementation libs.nordic.ui.scanner
|
||||||
|
implementation libs.nordic.navigation
|
||||||
|
|
||||||
implementation libs.bundles.koin
|
implementation libs.bundles.koin
|
||||||
implementation libs.bundles.hilt
|
implementation libs.bundles.hilt
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package no.nordicsemi.android.nrftoolbox
|
||||||
|
|
||||||
|
import no.nordicsemi.android.bps.repository.BPS_SERVICE_UUID
|
||||||
|
import no.nordicsemi.android.bps.view.BPSScreen
|
||||||
|
import no.nordicsemi.android.cgms.repository.CGMS_SERVICE_UUID
|
||||||
|
import no.nordicsemi.android.cgms.view.CGMScreen
|
||||||
|
import no.nordicsemi.android.csc.repository.CSC_SERVICE_UUID
|
||||||
|
import no.nordicsemi.android.csc.view.CSCScreen
|
||||||
|
import no.nordicsemi.android.gls.repository.GLS_SERVICE_UUID
|
||||||
|
import no.nordicsemi.android.gls.view.GLSScreen
|
||||||
|
import no.nordicsemi.android.hrs.service.HRS_SERVICE_UUID
|
||||||
|
import no.nordicsemi.android.hrs.view.HRSScreen
|
||||||
|
import no.nordicsemi.android.hts.repository.HTS_SERVICE_UUID
|
||||||
|
import no.nordicsemi.android.hts.view.HTSScreen
|
||||||
|
import no.nordicsemi.android.navigation.ComposeDestination
|
||||||
|
import no.nordicsemi.android.navigation.ComposeDestinations
|
||||||
|
import no.nordicsemi.android.prx.service.PRX_SERVICE_UUID
|
||||||
|
import no.nordicsemi.android.prx.view.PRXScreen
|
||||||
|
import no.nordicsemi.android.rscs.service.RSCS_SERVICE_UUID
|
||||||
|
import no.nordicsemi.android.rscs.view.RSCSScreen
|
||||||
|
import no.nordicsemi.android.uart.repository.UART_SERVICE_UUID
|
||||||
|
import no.nordicsemi.android.uart.view.UARTScreen
|
||||||
|
import no.nordicsemi.ui.scanner.navigation.view.FindDeviceScreen
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
val HomeDestinations = ComposeDestinations(HomeDestination.values().map { it.destination })
|
||||||
|
val ProfileDestinations = ComposeDestinations(ProfileDestination.values().map { it.destination })
|
||||||
|
|
||||||
|
enum class HomeDestination(val destination: ComposeDestination) {
|
||||||
|
HOME(ComposeDestination("home-destination") { HomeScreen() }),
|
||||||
|
SCANNER(ComposeDestination("scanner-destination") { FindDeviceScreen() });
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ProfileDestination(val destination: ComposeDestination, val uuid: UUID) {
|
||||||
|
CSC(ComposeDestination("csc-destination") { CSCScreen() }, CSC_SERVICE_UUID),
|
||||||
|
HRS(ComposeDestination("hrs-destination") { HRSScreen() }, HRS_SERVICE_UUID),
|
||||||
|
HTS(ComposeDestination("hts-destination") { HTSScreen() }, HTS_SERVICE_UUID),
|
||||||
|
GLS(ComposeDestination("gls-destination") { GLSScreen() }, GLS_SERVICE_UUID),
|
||||||
|
BPS(ComposeDestination("bps-destination") { BPSScreen() }, BPS_SERVICE_UUID),
|
||||||
|
PRX(ComposeDestination("prx-destination") { PRXScreen() }, PRX_SERVICE_UUID),
|
||||||
|
RSCS(ComposeDestination("rscs-destination") { RSCSScreen() }, RSCS_SERVICE_UUID),
|
||||||
|
CGMS(ComposeDestination("cgms-destination") { CGMScreen() }, CGMS_SERVICE_UUID),
|
||||||
|
UART(ComposeDestination("uart-destination") { UARTScreen() }, UART_SERVICE_UUID);
|
||||||
|
}
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
package no.nordicsemi.android.nrftoolbox
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.os.ParcelUuid
|
|
||||||
import androidx.activity.compose.BackHandler
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
|
||||||
import androidx.navigation.compose.NavHost
|
|
||||||
import androidx.navigation.compose.composable
|
|
||||||
import androidx.navigation.compose.rememberNavController
|
|
||||||
import no.nordicsemi.android.bps.view.BPSScreen
|
|
||||||
import no.nordicsemi.android.cgms.view.CGMScreen
|
|
||||||
import no.nordicsemi.android.csc.view.CSCScreen
|
|
||||||
import no.nordicsemi.android.gls.view.GLSScreen
|
|
||||||
import no.nordicsemi.android.hrs.view.HRSScreen
|
|
||||||
import no.nordicsemi.android.hts.view.HTSScreen
|
|
||||||
import no.nordicsemi.android.prx.view.PRXScreen
|
|
||||||
import no.nordicsemi.android.rscs.view.RSCSScreen
|
|
||||||
import no.nordicsemi.android.uart.view.UARTScreen
|
|
||||||
import no.nordicsemi.ui.scanner.navigation.view.FindDeviceScreen
|
|
||||||
import no.nordicsemi.ui.scanner.ui.exhaustive
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
internal fun HomeScreen() {
|
|
||||||
val navController = rememberNavController()
|
|
||||||
val viewModel: HomeViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val activity = LocalContext.current as Activity
|
|
||||||
BackHandler {
|
|
||||||
if (navController.currentDestination?.navigatorName != NavigationId.HOME.id) {
|
|
||||||
navController.popBackStack()
|
|
||||||
} else {
|
|
||||||
activity.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val destination = viewModel.destination.collectAsState()
|
|
||||||
|
|
||||||
val navigateUp = { viewModel.navigateUp() }
|
|
||||||
|
|
||||||
NavHost(
|
|
||||||
navController = navController,
|
|
||||||
startDestination = NavigationId.HOME.id
|
|
||||||
) {
|
|
||||||
composable(NavigationId.HOME.id) {
|
|
||||||
HomeView(viewModel)
|
|
||||||
}
|
|
||||||
composable(NavigationId.SCANNER.id) {
|
|
||||||
val profile = viewModel.profile!!
|
|
||||||
FindDeviceScreen(ParcelUuid(profile.uuid)) {
|
|
||||||
viewModel.onScannerFlowResult(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
composable(NavigationId.CSC.id) {
|
|
||||||
CSCScreen(navigateUp)
|
|
||||||
}
|
|
||||||
composable(NavigationId.HRS.id) {
|
|
||||||
HRSScreen(navigateUp)
|
|
||||||
}
|
|
||||||
composable(NavigationId.HTS.id) {
|
|
||||||
HTSScreen(navigateUp)
|
|
||||||
}
|
|
||||||
composable(NavigationId.GLS.id) {
|
|
||||||
GLSScreen(navigateUp)
|
|
||||||
}
|
|
||||||
composable(NavigationId.BPS.id) {
|
|
||||||
BPSScreen(navigateUp)
|
|
||||||
}
|
|
||||||
composable(NavigationId.PRX.id) {
|
|
||||||
PRXScreen(navigateUp)
|
|
||||||
}
|
|
||||||
composable(NavigationId.RSCS.id) {
|
|
||||||
RSCSScreen(navigateUp)
|
|
||||||
}
|
|
||||||
composable(NavigationId.CGMS.id) {
|
|
||||||
CGMScreen(navigateUp)
|
|
||||||
}
|
|
||||||
composable(NavigationId.UART.id) {
|
|
||||||
UARTScreen(navigateUp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val context = LocalContext.current as Activity
|
|
||||||
LaunchedEffect(destination.value) {
|
|
||||||
when (val destination = destination.value) {
|
|
||||||
FinishDestination -> context.finish()
|
|
||||||
HomeDestination -> navController.navigateUp()
|
|
||||||
is ProfileDestination -> {
|
|
||||||
navController.navigateUp()
|
|
||||||
navController.navigate(destination.id.id)
|
|
||||||
}
|
|
||||||
is ScannerDestination -> navController.navigate(destination.id.id)
|
|
||||||
}.exhaustive
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,10 +18,13 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import no.nordicsemi.android.theme.view.CloseIconAppBar
|
import no.nordicsemi.android.theme.view.CloseIconAppBar
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HomeView(viewModel: HomeViewModel) {
|
fun HomeScreen() {
|
||||||
|
val viewModel: HomeViewModel = hiltViewModel()
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
CloseIconAppBar(stringResource(id = R.string.app_name)) {
|
CloseIconAppBar(stringResource(id = R.string.app_name)) {
|
||||||
@@ -43,12 +46,12 @@ fun HomeView(viewModel: HomeViewModel) {
|
|||||||
DoubleSection(
|
DoubleSection(
|
||||||
leftView = {
|
leftView = {
|
||||||
FeatureButton(R.drawable.ic_csc, R.string.csc_module, R.string.csc_module_full) {
|
FeatureButton(R.drawable.ic_csc, R.string.csc_module, R.string.csc_module_full) {
|
||||||
viewModel.openProfile(Profile.CSC)
|
viewModel.openProfile(ProfileDestination.CSC)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rightView = {
|
rightView = {
|
||||||
FeatureButton(R.drawable.ic_hrs, R.string.hrs_module, R.string.hrs_module_full) {
|
FeatureButton(R.drawable.ic_hrs, R.string.hrs_module, R.string.hrs_module_full) {
|
||||||
viewModel.openProfile(Profile.HRS)
|
viewModel.openProfile(ProfileDestination.HRS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -58,12 +61,12 @@ fun HomeView(viewModel: HomeViewModel) {
|
|||||||
DoubleSection(
|
DoubleSection(
|
||||||
leftView = {
|
leftView = {
|
||||||
FeatureButton(R.drawable.ic_gls, R.string.gls_module, R.string.gls_module_full) {
|
FeatureButton(R.drawable.ic_gls, R.string.gls_module, R.string.gls_module_full) {
|
||||||
viewModel.openProfile(Profile.GLS)
|
viewModel.openProfile(ProfileDestination.GLS)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rightView = {
|
rightView = {
|
||||||
FeatureButton(R.drawable.ic_hts, R.string.hts_module, R.string.hts_module_full) {
|
FeatureButton(R.drawable.ic_hts, R.string.hts_module, R.string.hts_module_full) {
|
||||||
viewModel.openProfile(Profile.HTS)
|
viewModel.openProfile(ProfileDestination.HTS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -73,12 +76,12 @@ fun HomeView(viewModel: HomeViewModel) {
|
|||||||
DoubleSection(
|
DoubleSection(
|
||||||
leftView = {
|
leftView = {
|
||||||
FeatureButton(R.drawable.ic_bps, R.string.bps_module, R.string.bps_module_full) {
|
FeatureButton(R.drawable.ic_bps, R.string.bps_module, R.string.bps_module_full) {
|
||||||
viewModel.openProfile(Profile.BPS)
|
viewModel.openProfile(ProfileDestination.BPS)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rightView = {
|
rightView = {
|
||||||
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) {
|
||||||
viewModel.openProfile(Profile.RSCS)
|
viewModel.openProfile(ProfileDestination.RSCS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -88,12 +91,12 @@ fun HomeView(viewModel: HomeViewModel) {
|
|||||||
DoubleSection(
|
DoubleSection(
|
||||||
leftView = {
|
leftView = {
|
||||||
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) {
|
||||||
viewModel.openProfile(Profile.PRX)
|
viewModel.openProfile(ProfileDestination.PRX)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rightView = {
|
rightView = {
|
||||||
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) {
|
||||||
viewModel.openProfile(Profile.CGMS)
|
viewModel.openProfile(ProfileDestination.CGMS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -101,7 +104,7 @@ fun HomeView(viewModel: HomeViewModel) {
|
|||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
FeatureButton(R.drawable.ic_uart, R.string.uart_module, R.string.uart_module_full) {
|
FeatureButton(R.drawable.ic_uart, R.string.uart_module, R.string.uart_module_full) {
|
||||||
viewModel.openProfile(Profile.UART)
|
viewModel.openProfile(ProfileDestination.UART)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|||||||
@@ -2,50 +2,22 @@ package no.nordicsemi.android.nrftoolbox
|
|||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import no.nordicsemi.android.navigation.ForwardDestination
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import no.nordicsemi.android.navigation.NavigationManager
|
||||||
|
import no.nordicsemi.android.navigation.UUIDArgument
|
||||||
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
||||||
import no.nordicsemi.ui.scanner.navigation.view.FindDeviceCloseResult
|
|
||||||
import no.nordicsemi.ui.scanner.navigation.view.FindDeviceFlowStatus
|
|
||||||
import no.nordicsemi.ui.scanner.navigation.view.FindDeviceSuccessResult
|
|
||||||
import no.nordicsemi.ui.scanner.ui.exhaustive
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class HomeViewModel @Inject constructor(
|
class HomeViewModel @Inject constructor(
|
||||||
private val deviceHolder: SelectedBluetoothDeviceHolder
|
private val deviceHolder: SelectedBluetoothDeviceHolder,
|
||||||
|
private val navigationManager: NavigationManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val _destination = MutableStateFlow<NavDestination>(HomeDestination)
|
fun openProfile(destination: ProfileDestination) {
|
||||||
val destination = _destination.asStateFlow()
|
navigationManager.navigateTo(
|
||||||
|
ForwardDestination(destination.destination.id),
|
||||||
var profile: Profile? = null //to pass argument between nav destinations
|
UUIDArgument(destination.uuid)
|
||||||
|
)
|
||||||
fun onScannerFlowResult(status: FindDeviceFlowStatus) {
|
|
||||||
when (status) {
|
|
||||||
FindDeviceCloseResult -> navigateUp()
|
|
||||||
is FindDeviceSuccessResult -> onDeviceSelected(status)
|
|
||||||
}.exhaustive
|
|
||||||
}
|
|
||||||
|
|
||||||
fun openProfile(profile: Profile) {
|
|
||||||
this.profile = profile
|
|
||||||
_destination.value = ScannerDestination(profile)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun navigateUp() {
|
|
||||||
val currentDestination = _destination.value
|
|
||||||
_destination.value = when (currentDestination) {
|
|
||||||
FinishDestination -> FinishDestination
|
|
||||||
HomeDestination -> FinishDestination
|
|
||||||
is ProfileDestination -> HomeDestination
|
|
||||||
is ScannerDestination -> HomeDestination
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onDeviceSelected(result: FindDeviceSuccessResult) {
|
|
||||||
val profile = requireNotNull(profile)
|
|
||||||
deviceHolder.attachDevice(result.device)
|
|
||||||
_destination.value = ProfileDestination(profile.toNavigationId(), profile.isPairingRequired)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import androidx.compose.ui.Modifier
|
|||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import no.nordicsemi.android.material.you.NordicActivity
|
import no.nordicsemi.android.material.you.NordicActivity
|
||||||
import no.nordicsemi.android.material.you.NordicTheme
|
import no.nordicsemi.android.material.you.NordicTheme
|
||||||
|
import no.nordicsemi.android.navigation.NavigationView
|
||||||
|
import no.nordicsemi.ui.scanner.ScannerDestinations
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : NordicActivity() {
|
class MainActivity : NordicActivity() {
|
||||||
@@ -22,7 +24,9 @@ class MainActivity : NordicActivity() {
|
|||||||
color = MaterialTheme.colorScheme.surface,
|
color = MaterialTheme.colorScheme.surface,
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
HomeScreen()
|
NavigationView(
|
||||||
|
HomeDestinations + ProfileDestinations + ScannerDestinations
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
package no.nordicsemi.android.nrftoolbox
|
|
||||||
|
|
||||||
sealed class NavDestination
|
|
||||||
|
|
||||||
object FinishDestination : NavDestination()
|
|
||||||
|
|
||||||
sealed class ForwardDestination : NavDestination() {
|
|
||||||
abstract val id: NavigationId
|
|
||||||
}
|
|
||||||
|
|
||||||
object HomeDestination : ForwardDestination() {
|
|
||||||
override val id: NavigationId = NavigationId.HOME
|
|
||||||
}
|
|
||||||
|
|
||||||
data class ScannerDestination(val profile: Profile) : ForwardDestination() {
|
|
||||||
override val id: NavigationId = NavigationId.SCANNER
|
|
||||||
}
|
|
||||||
|
|
||||||
data class ProfileDestination(
|
|
||||||
override val id: NavigationId,
|
|
||||||
val isPairingRequired: Boolean
|
|
||||||
) : ForwardDestination()
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package no.nordicsemi.android.nrftoolbox
|
|
||||||
|
|
||||||
import android.os.Parcelable
|
|
||||||
import kotlinx.parcelize.Parcelize
|
|
||||||
import no.nordicsemi.android.bps.repository.BPS_SERVICE_UUID
|
|
||||||
import no.nordicsemi.android.cgms.repository.CGMS_SERVICE_UUID
|
|
||||||
import no.nordicsemi.android.csc.repository.CYCLING_SPEED_AND_CADENCE_SERVICE_UUID
|
|
||||||
import no.nordicsemi.android.gls.repository.GLS_SERVICE_UUID
|
|
||||||
import no.nordicsemi.android.hrs.service.HR_SERVICE_UUID
|
|
||||||
import no.nordicsemi.android.hts.repository.HT_SERVICE_UUID
|
|
||||||
import no.nordicsemi.android.prx.service.PRX_SERVICE_UUID
|
|
||||||
import no.nordicsemi.android.rscs.service.RSCS_SERVICE_UUID
|
|
||||||
import no.nordicsemi.android.uart.repository.UART_SERVICE_UUID
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
enum class NavigationId(val id: String) {
|
|
||||||
HOME("home-screen"),
|
|
||||||
SCANNER("scanner-screen"),
|
|
||||||
CSC("csc-screen"),
|
|
||||||
HRS("hrs-screen"),
|
|
||||||
HTS("hts-screen"),
|
|
||||||
GLS("gls-screen"),
|
|
||||||
BPS("bps-screen"),
|
|
||||||
PRX("prx-screen"),
|
|
||||||
RSCS("rscs-screen"),
|
|
||||||
CGMS("cgms-screen"),
|
|
||||||
UART("uart-screen");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
enum class Profile(val uuid: UUID, val isPairingRequired: Boolean) : Parcelable {
|
|
||||||
CSC(CYCLING_SPEED_AND_CADENCE_SERVICE_UUID, false),
|
|
||||||
HRS(HR_SERVICE_UUID, false),
|
|
||||||
HTS(HT_SERVICE_UUID, false),
|
|
||||||
GLS(GLS_SERVICE_UUID, true),
|
|
||||||
BPS(BPS_SERVICE_UUID, false),
|
|
||||||
PRX(PRX_SERVICE_UUID, true),
|
|
||||||
RSCS(RSCS_SERVICE_UUID, false),
|
|
||||||
CGMS(CGMS_SERVICE_UUID, false),
|
|
||||||
UART(UART_SERVICE_UUID, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Profile.toNavigationId(): NavigationId {
|
|
||||||
return when (this) {
|
|
||||||
Profile.CSC -> NavigationId.CSC
|
|
||||||
Profile.HRS -> NavigationId.HRS
|
|
||||||
Profile.HTS -> NavigationId.HTS
|
|
||||||
Profile.GLS -> NavigationId.GLS
|
|
||||||
Profile.BPS -> NavigationId.BPS
|
|
||||||
Profile.PRX -> NavigationId.PRX
|
|
||||||
Profile.RSCS -> NavigationId.RSCS
|
|
||||||
Profile.CGMS -> NavigationId.CGMS
|
|
||||||
Profile.UART -> NavigationId.UART
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,7 @@ dependencies {
|
|||||||
implementation project(":lib_utils")
|
implementation project(":lib_utils")
|
||||||
|
|
||||||
implementation libs.nordic.ble.common
|
implementation libs.nordic.ble.common
|
||||||
|
implementation libs.nordic.navigation
|
||||||
|
|
||||||
implementation libs.nordic.log
|
implementation libs.nordic.log
|
||||||
implementation libs.nordic.ui.scanner
|
implementation libs.nordic.ui.scanner
|
||||||
|
|||||||
@@ -13,19 +13,15 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
|
|||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BPSScreen(finishAction: () -> Unit) {
|
fun BPSScreen() {
|
||||||
val viewModel: BPSViewModel = hiltViewModel()
|
val viewModel: BPSViewModel = hiltViewModel()
|
||||||
val state = viewModel.state.collectAsState().value
|
val state = viewModel.state.collectAsState().value
|
||||||
|
|
||||||
LaunchedEffect(state.isActive) {
|
LaunchedEffect(Unit) {
|
||||||
if (state.isActive) {
|
viewModel.connectDevice()
|
||||||
viewModel.connectDevice()
|
|
||||||
} else {
|
|
||||||
finishAction()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BPSView(state.viewState) { viewModel.onEvent(it) }
|
BPSView(state) { viewModel.onEvent(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ package no.nordicsemi.android.bps.view
|
|||||||
|
|
||||||
import no.nordicsemi.android.bps.data.BPSData
|
import no.nordicsemi.android.bps.data.BPSData
|
||||||
|
|
||||||
internal data class BPSState(
|
|
||||||
val viewState: BPSViewState,
|
|
||||||
val isActive: Boolean = true
|
|
||||||
)
|
|
||||||
|
|
||||||
internal sealed class BPSViewState
|
internal sealed class BPSViewState
|
||||||
|
|
||||||
internal object LoadingState : BPSViewState()
|
internal object LoadingState : BPSViewState()
|
||||||
|
|||||||
@@ -6,14 +6,16 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import no.nordicsemi.android.bps.data.BPSRepository
|
import no.nordicsemi.android.bps.data.BPSRepository
|
||||||
import no.nordicsemi.android.bps.repository.BPSManager
|
import no.nordicsemi.android.bps.repository.BPSManager
|
||||||
import no.nordicsemi.android.bps.view.BPSScreenViewEvent
|
import no.nordicsemi.android.bps.view.BPSScreenViewEvent
|
||||||
import no.nordicsemi.android.bps.view.BPSState
|
|
||||||
import no.nordicsemi.android.bps.view.DisconnectEvent
|
import no.nordicsemi.android.bps.view.DisconnectEvent
|
||||||
import no.nordicsemi.android.bps.view.DisplayDataState
|
import no.nordicsemi.android.bps.view.DisplayDataState
|
||||||
import no.nordicsemi.android.bps.view.LoadingState
|
import no.nordicsemi.android.bps.view.LoadingState
|
||||||
|
import no.nordicsemi.android.navigation.NavigationManager
|
||||||
import no.nordicsemi.android.service.BleManagerStatus
|
import no.nordicsemi.android.service.BleManagerStatus
|
||||||
import no.nordicsemi.android.service.ConnectionObserverAdapter
|
import no.nordicsemi.android.service.ConnectionObserverAdapter
|
||||||
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
||||||
@@ -24,16 +26,17 @@ import javax.inject.Inject
|
|||||||
internal class BPSViewModel @Inject constructor(
|
internal class BPSViewModel @Inject constructor(
|
||||||
private val bpsManager: BPSManager,
|
private val bpsManager: BPSManager,
|
||||||
private val deviceHolder: SelectedBluetoothDeviceHolder,
|
private val deviceHolder: SelectedBluetoothDeviceHolder,
|
||||||
private val repository: BPSRepository
|
private val repository: BPSRepository,
|
||||||
|
private val navigationManager: NavigationManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val state = repository.data.combine(repository.status) { data, status ->
|
val state = repository.data.combine(repository.status) { data, status ->
|
||||||
when (status) {
|
when (status) {
|
||||||
BleManagerStatus.CONNECTING -> BPSState(LoadingState)
|
BleManagerStatus.CONNECTING -> LoadingState
|
||||||
BleManagerStatus.OK -> BPSState(DisplayDataState(data))
|
BleManagerStatus.OK,
|
||||||
BleManagerStatus.DISCONNECTED -> BPSState(DisplayDataState(data), false)
|
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
|
||||||
}
|
}
|
||||||
}.stateIn(viewModelScope, SharingStarted.Lazily, BPSState(LoadingState))
|
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
bpsManager.setConnectionObserver(object : ConnectionObserverAdapter() {
|
bpsManager.setConnectionObserver(object : ConnectionObserverAdapter() {
|
||||||
@@ -52,6 +55,12 @@ internal class BPSViewModel @Inject constructor(
|
|||||||
repository.setNewStatus(BleManagerStatus.DISCONNECTED)
|
repository.setNewStatus(BleManagerStatus.DISCONNECTED)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
repository.status.onEach {
|
||||||
|
if (it == BleManagerStatus.DISCONNECTED) {
|
||||||
|
navigationManager.navigateUp()
|
||||||
|
}
|
||||||
|
}.launchIn(viewModelScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEvent(event: BPSScreenViewEvent) {
|
fun onEvent(event: BPSScreenViewEvent) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation libs.nordic.log
|
implementation libs.nordic.log
|
||||||
implementation libs.nordic.theme
|
implementation libs.nordic.theme
|
||||||
|
implementation libs.nordic.navigation
|
||||||
|
|
||||||
implementation libs.bundles.compose
|
implementation libs.bundles.compose
|
||||||
implementation libs.androidx.core
|
implementation libs.androidx.core
|
||||||
|
|||||||
@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
|
|||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CGMScreen(finishAction: () -> Unit) {
|
fun CGMScreen() {
|
||||||
val viewModel: CGMScreenViewModel = hiltViewModel()
|
val viewModel: CGMScreenViewModel = hiltViewModel()
|
||||||
val state = viewModel.state.collectAsState().value
|
val state = viewModel.state.collectAsState().value
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
LaunchedEffect(state.isActive) {
|
LaunchedEffect(Unit) {
|
||||||
if (state.isActive) {
|
val intent = Intent(context, CGMService::class.java)
|
||||||
val intent = Intent(context, CGMService::class.java)
|
context.startService(intent)
|
||||||
context.startService(intent)
|
|
||||||
} else if (!state.isActive) {
|
|
||||||
finishAction()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CGMView(state.viewState) {
|
CGMView(state) {
|
||||||
viewModel.onEvent(it)
|
viewModel.onEvent(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ package no.nordicsemi.android.cgms.view
|
|||||||
|
|
||||||
import no.nordicsemi.android.cgms.data.CGMData
|
import no.nordicsemi.android.cgms.data.CGMData
|
||||||
|
|
||||||
internal data class CGMState(
|
|
||||||
val viewState: CGMViewState,
|
|
||||||
val isActive: Boolean = true
|
|
||||||
)
|
|
||||||
|
|
||||||
internal sealed class CGMViewState
|
internal sealed class CGMViewState
|
||||||
|
|
||||||
internal object LoadingState : CGMViewState()
|
internal object LoadingState : CGMViewState()
|
||||||
|
|||||||
@@ -5,31 +5,42 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import no.nordicsemi.android.cgms.data.CGMRepository
|
import no.nordicsemi.android.cgms.data.CGMRepository
|
||||||
import no.nordicsemi.android.cgms.data.CGMServiceCommand
|
import no.nordicsemi.android.cgms.data.CGMServiceCommand
|
||||||
import no.nordicsemi.android.cgms.view.CGMState
|
|
||||||
import no.nordicsemi.android.cgms.view.CGMViewEvent
|
import no.nordicsemi.android.cgms.view.CGMViewEvent
|
||||||
import no.nordicsemi.android.cgms.view.DisconnectEvent
|
import no.nordicsemi.android.cgms.view.DisconnectEvent
|
||||||
import no.nordicsemi.android.cgms.view.DisplayDataState
|
import no.nordicsemi.android.cgms.view.DisplayDataState
|
||||||
import no.nordicsemi.android.cgms.view.LoadingState
|
import no.nordicsemi.android.cgms.view.LoadingState
|
||||||
import no.nordicsemi.android.cgms.view.OnWorkingModeSelected
|
import no.nordicsemi.android.cgms.view.OnWorkingModeSelected
|
||||||
|
import no.nordicsemi.android.navigation.NavigationManager
|
||||||
import no.nordicsemi.android.service.BleManagerStatus
|
import no.nordicsemi.android.service.BleManagerStatus
|
||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
internal class CGMScreenViewModel @Inject constructor(
|
internal class CGMScreenViewModel @Inject constructor(
|
||||||
private val repository: CGMRepository
|
private val repository: CGMRepository,
|
||||||
|
private val navigationManager: NavigationManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val state = repository.data.combine(repository.status) { data, status ->
|
val state = repository.data.combine(repository.status) { data, status ->
|
||||||
when (status) {
|
when (status) {
|
||||||
BleManagerStatus.CONNECTING -> CGMState(LoadingState)
|
BleManagerStatus.CONNECTING -> LoadingState
|
||||||
BleManagerStatus.OK -> CGMState(DisplayDataState(data))
|
BleManagerStatus.OK,
|
||||||
BleManagerStatus.DISCONNECTED -> CGMState(DisplayDataState(data), false)
|
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
|
||||||
}
|
}
|
||||||
}.stateIn(viewModelScope, SharingStarted.Lazily, CGMState(LoadingState))
|
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
|
||||||
|
|
||||||
|
init {
|
||||||
|
repository.status.onEach {
|
||||||
|
if (it == BleManagerStatus.DISCONNECTED) {
|
||||||
|
navigationManager.navigateUp()
|
||||||
|
}
|
||||||
|
}.launchIn(viewModelScope)
|
||||||
|
}
|
||||||
|
|
||||||
fun onEvent(event: CGMViewEvent) {
|
fun onEvent(event: CGMViewEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation libs.nordic.log
|
implementation libs.nordic.log
|
||||||
implementation libs.nordic.theme
|
implementation libs.nordic.theme
|
||||||
|
implementation libs.nordic.navigation
|
||||||
|
|
||||||
implementation libs.bundles.compose
|
implementation libs.bundles.compose
|
||||||
implementation libs.androidx.core
|
implementation libs.androidx.core
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import no.nordicsemi.android.service.BatteryManager
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/** Cycling Speed and Cadence service UUID. */
|
/** Cycling Speed and Cadence service UUID. */
|
||||||
val CYCLING_SPEED_AND_CADENCE_SERVICE_UUID: UUID = UUID.fromString("00001816-0000-1000-8000-00805f9b34fb")
|
val CSC_SERVICE_UUID: UUID = UUID.fromString("00001816-0000-1000-8000-00805f9b34fb")
|
||||||
|
|
||||||
/** Cycling Speed and Cadence Measurement characteristic UUID. */
|
/** Cycling Speed and Cadence Measurement characteristic UUID. */
|
||||||
private val CSC_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A5B-0000-1000-8000-00805f9b34fb")
|
private val CSC_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A5B-0000-1000-8000-00805f9b34fb")
|
||||||
@@ -101,7 +101,7 @@ internal class CSCManager(context: Context, private val repository: CSCRepositor
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
|
public override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
|
||||||
val service = gatt.getService(CYCLING_SPEED_AND_CADENCE_SERVICE_UUID)
|
val service = gatt.getService(CSC_SERVICE_UUID)
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
cscMeasurementCharacteristic = service.getCharacteristic(
|
cscMeasurementCharacteristic = service.getCharacteristic(
|
||||||
CSC_MEASUREMENT_CHARACTERISTIC_UUID
|
CSC_MEASUREMENT_CHARACTERISTIC_UUID
|
||||||
|
|||||||
@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
|
|||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CSCScreen(finishAction: () -> Unit) {
|
fun CSCScreen() {
|
||||||
val viewModel: CSCViewModel = hiltViewModel()
|
val viewModel: CSCViewModel = hiltViewModel()
|
||||||
val state = viewModel.state.collectAsState().value
|
val state = viewModel.state.collectAsState().value
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
LaunchedEffect(state.isActive) {
|
LaunchedEffect(Unit) {
|
||||||
if (state.isActive) {
|
val intent = Intent(context, CSCService::class.java)
|
||||||
val intent = Intent(context, CSCService::class.java)
|
context.startService(intent)
|
||||||
context.startService(intent)
|
|
||||||
} else {
|
|
||||||
finishAction()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSCView(state.viewState) { viewModel.onEvent(it) }
|
CSCView(state) { viewModel.onEvent(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ package no.nordicsemi.android.csc.view
|
|||||||
|
|
||||||
import no.nordicsemi.android.csc.data.CSCData
|
import no.nordicsemi.android.csc.data.CSCData
|
||||||
|
|
||||||
internal data class CSCState(
|
|
||||||
val viewState: CSCViewState,
|
|
||||||
val isActive: Boolean = true
|
|
||||||
)
|
|
||||||
|
|
||||||
internal sealed class CSCViewState
|
internal sealed class CSCViewState
|
||||||
|
|
||||||
internal object LoadingState : CSCViewState()
|
internal object LoadingState : CSCViewState()
|
||||||
|
|||||||
@@ -5,33 +5,44 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import no.nordicsemi.android.csc.data.CSCRepository
|
import no.nordicsemi.android.csc.data.CSCRepository
|
||||||
import no.nordicsemi.android.csc.data.DisconnectCommand
|
import no.nordicsemi.android.csc.data.DisconnectCommand
|
||||||
import no.nordicsemi.android.csc.data.SetWheelSizeCommand
|
import no.nordicsemi.android.csc.data.SetWheelSizeCommand
|
||||||
import no.nordicsemi.android.csc.view.CSCState
|
|
||||||
import no.nordicsemi.android.csc.view.CSCViewEvent
|
import no.nordicsemi.android.csc.view.CSCViewEvent
|
||||||
import no.nordicsemi.android.csc.view.DisplayDataState
|
import no.nordicsemi.android.csc.view.DisplayDataState
|
||||||
import no.nordicsemi.android.csc.view.LoadingState
|
import no.nordicsemi.android.csc.view.LoadingState
|
||||||
import no.nordicsemi.android.csc.view.OnDisconnectButtonClick
|
import no.nordicsemi.android.csc.view.OnDisconnectButtonClick
|
||||||
import no.nordicsemi.android.csc.view.OnSelectedSpeedUnitSelected
|
import no.nordicsemi.android.csc.view.OnSelectedSpeedUnitSelected
|
||||||
import no.nordicsemi.android.csc.view.OnWheelSizeSelected
|
import no.nordicsemi.android.csc.view.OnWheelSizeSelected
|
||||||
|
import no.nordicsemi.android.navigation.NavigationManager
|
||||||
import no.nordicsemi.android.service.BleManagerStatus
|
import no.nordicsemi.android.service.BleManagerStatus
|
||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
internal class CSCViewModel @Inject constructor(
|
internal class CSCViewModel @Inject constructor(
|
||||||
private val repository: CSCRepository
|
private val repository: CSCRepository,
|
||||||
|
private val navigationManager: NavigationManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val state = repository.data.combine(repository.status) { data, status ->
|
val state = repository.data.combine(repository.status) { data, status ->
|
||||||
when (status) {
|
when (status) {
|
||||||
BleManagerStatus.CONNECTING -> CSCState(LoadingState)
|
BleManagerStatus.CONNECTING -> LoadingState
|
||||||
BleManagerStatus.OK -> CSCState(DisplayDataState(data))
|
BleManagerStatus.OK,
|
||||||
BleManagerStatus.DISCONNECTED -> CSCState(DisplayDataState(data), false)
|
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
|
||||||
}
|
}
|
||||||
}.stateIn(viewModelScope, SharingStarted.Lazily, CSCState(LoadingState))
|
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
|
||||||
|
|
||||||
|
init {
|
||||||
|
repository.status.onEach {
|
||||||
|
if (it == BleManagerStatus.DISCONNECTED) {
|
||||||
|
navigationManager.navigateUp()
|
||||||
|
}
|
||||||
|
}.launchIn(viewModelScope)
|
||||||
|
}
|
||||||
|
|
||||||
fun onEvent(event: CSCViewEvent) {
|
fun onEvent(event: CSCViewEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation libs.nordic.ble.common
|
implementation libs.nordic.ble.common
|
||||||
implementation libs.nordic.theme
|
implementation libs.nordic.theme
|
||||||
|
implementation libs.nordic.navigation
|
||||||
|
|
||||||
implementation libs.nordic.log
|
implementation libs.nordic.log
|
||||||
implementation libs.nordic.dfu
|
implementation libs.nordic.dfu
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ dependencies {
|
|||||||
implementation libs.nordic.ble.common
|
implementation libs.nordic.ble.common
|
||||||
implementation libs.nordic.theme
|
implementation libs.nordic.theme
|
||||||
implementation libs.nordic.ui.scanner
|
implementation libs.nordic.ui.scanner
|
||||||
|
implementation libs.nordic.navigation
|
||||||
|
|
||||||
implementation libs.nordic.log
|
implementation libs.nordic.log
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ package no.nordicsemi.android.gls.view
|
|||||||
|
|
||||||
import no.nordicsemi.android.gls.data.GLSData
|
import no.nordicsemi.android.gls.data.GLSData
|
||||||
|
|
||||||
internal data class GLSState(
|
|
||||||
val viewState: GLSViewState,
|
|
||||||
val isActive: Boolean = true
|
|
||||||
)
|
|
||||||
|
|
||||||
internal sealed class GLSViewState
|
internal sealed class GLSViewState
|
||||||
|
|
||||||
internal object LoadingState : GLSViewState()
|
internal object LoadingState : GLSViewState()
|
||||||
|
|||||||
@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
|
|||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun GLSScreen(finishAction: () -> Unit) {
|
fun GLSScreen() {
|
||||||
val viewModel: GLSViewModel = hiltViewModel()
|
val viewModel: GLSViewModel = hiltViewModel()
|
||||||
val state = viewModel.state.collectAsState().value
|
val state = viewModel.state.collectAsState().value
|
||||||
|
|
||||||
Log.d("AAATESTAAA", "$viewModel") //TODO fix screen rotation
|
Log.d("AAATESTAAA", "$viewModel") //TODO fix screen rotation
|
||||||
|
|
||||||
LaunchedEffect(state.isActive) {
|
LaunchedEffect(Unit) {
|
||||||
if (state.isActive) {
|
viewModel.connectDevice()
|
||||||
viewModel.connectDevice()
|
|
||||||
} else {
|
|
||||||
finishAction()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLSView(state.viewState) {
|
GLSView(state) {
|
||||||
viewModel.onEvent(it)
|
viewModel.onEvent(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import no.nordicsemi.android.gls.data.GLSRepository
|
import no.nordicsemi.android.gls.data.GLSRepository
|
||||||
import no.nordicsemi.android.gls.data.WorkingMode
|
import no.nordicsemi.android.gls.data.WorkingMode
|
||||||
import no.nordicsemi.android.gls.repository.GLSManager
|
import no.nordicsemi.android.gls.repository.GLSManager
|
||||||
import no.nordicsemi.android.gls.view.DisplayDataState
|
import no.nordicsemi.android.gls.view.DisplayDataState
|
||||||
import no.nordicsemi.android.gls.view.GLSState
|
|
||||||
import no.nordicsemi.android.gls.view.LoadingState
|
import no.nordicsemi.android.gls.view.LoadingState
|
||||||
|
import no.nordicsemi.android.navigation.NavigationManager
|
||||||
import no.nordicsemi.android.service.BleManagerStatus
|
import no.nordicsemi.android.service.BleManagerStatus
|
||||||
import no.nordicsemi.android.service.ConnectionObserverAdapter
|
import no.nordicsemi.android.service.ConnectionObserverAdapter
|
||||||
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
||||||
@@ -23,16 +25,17 @@ import javax.inject.Inject
|
|||||||
internal class GLSViewModel @Inject constructor(
|
internal class GLSViewModel @Inject constructor(
|
||||||
private val glsManager: GLSManager,
|
private val glsManager: GLSManager,
|
||||||
private val deviceHolder: SelectedBluetoothDeviceHolder,
|
private val deviceHolder: SelectedBluetoothDeviceHolder,
|
||||||
private val repository: GLSRepository
|
private val repository: GLSRepository,
|
||||||
|
private val navigationManager: NavigationManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val state = repository.data.combine(repository.status) { data, status ->
|
val state = repository.data.combine(repository.status) { data, status ->
|
||||||
when (status) {
|
when (status) {
|
||||||
BleManagerStatus.CONNECTING -> GLSState(LoadingState)
|
BleManagerStatus.CONNECTING -> LoadingState
|
||||||
BleManagerStatus.OK -> GLSState(DisplayDataState(data))
|
BleManagerStatus.OK,
|
||||||
BleManagerStatus.DISCONNECTED -> GLSState(DisplayDataState(data), false)
|
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
|
||||||
}
|
}
|
||||||
}.stateIn(viewModelScope, SharingStarted.Lazily, GLSState(LoadingState))
|
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
glsManager.setConnectionObserver(object : ConnectionObserverAdapter() {
|
glsManager.setConnectionObserver(object : ConnectionObserverAdapter() {
|
||||||
@@ -51,6 +54,12 @@ internal class GLSViewModel @Inject constructor(
|
|||||||
repository.setNewStatus(BleManagerStatus.DISCONNECTED)
|
repository.setNewStatus(BleManagerStatus.DISCONNECTED)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
repository.status.onEach {
|
||||||
|
if (it == BleManagerStatus.DISCONNECTED) {
|
||||||
|
navigationManager.navigateUp()
|
||||||
|
}
|
||||||
|
}.launchIn(viewModelScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEvent(event: GLSScreenViewEvent) {
|
fun onEvent(event: GLSScreenViewEvent) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ dependencies {
|
|||||||
implementation libs.chart
|
implementation libs.chart
|
||||||
|
|
||||||
implementation libs.nordic.ble.common
|
implementation libs.nordic.ble.common
|
||||||
|
implementation libs.nordic.navigation
|
||||||
|
|
||||||
implementation libs.nordic.log
|
implementation libs.nordic.log
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import no.nordicsemi.android.hrs.data.HRSRepository
|
|||||||
import no.nordicsemi.android.service.BatteryManager
|
import no.nordicsemi.android.service.BatteryManager
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
val HR_SERVICE_UUID: UUID = UUID.fromString("0000180D-0000-1000-8000-00805f9b34fb")
|
val HRS_SERVICE_UUID: UUID = UUID.fromString("0000180D-0000-1000-8000-00805f9b34fb")
|
||||||
private val BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID = UUID.fromString("00002A38-0000-1000-8000-00805f9b34fb")
|
private val BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID = UUID.fromString("00002A38-0000-1000-8000-00805f9b34fb")
|
||||||
private val HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A37-0000-1000-8000-00805f9b34fb")
|
private val HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A37-0000-1000-8000-00805f9b34fb")
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ internal class HRSManager(context: Context, private val dataHolder: HRSRepositor
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
|
override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
|
||||||
val service = gatt.getService(HR_SERVICE_UUID)
|
val service = gatt.getService(HRS_SERVICE_UUID)
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
heartRateCharacteristic = service.getCharacteristic(
|
heartRateCharacteristic = service.getCharacteristic(
|
||||||
HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID
|
HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID
|
||||||
@@ -111,7 +111,7 @@ internal class HRSManager(context: Context, private val dataHolder: HRSRepositor
|
|||||||
|
|
||||||
override fun isOptionalServiceSupported(gatt: BluetoothGatt): Boolean {
|
override fun isOptionalServiceSupported(gatt: BluetoothGatt): Boolean {
|
||||||
super.isOptionalServiceSupported(gatt)
|
super.isOptionalServiceSupported(gatt)
|
||||||
val service = gatt.getService(HR_SERVICE_UUID)
|
val service = gatt.getService(HRS_SERVICE_UUID)
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
bodySensorLocationCharacteristic = service.getCharacteristic(
|
bodySensorLocationCharacteristic = service.getCharacteristic(
|
||||||
BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID
|
BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID
|
||||||
|
|||||||
@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
|
|||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HRSScreen(finishAction: () -> Unit) {
|
fun HRSScreen() {
|
||||||
val viewModel: HRSViewModel = hiltViewModel()
|
val viewModel: HRSViewModel = hiltViewModel()
|
||||||
val state = viewModel.state.collectAsState().value
|
val state = viewModel.state.collectAsState().value
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
LaunchedEffect(state.isActive) {
|
LaunchedEffect(Unit) {
|
||||||
if (state.isActive) {
|
val intent = Intent(context, HRSService::class.java)
|
||||||
val intent = Intent(context, HRSService::class.java)
|
context.startService(intent)
|
||||||
context.startService(intent)
|
|
||||||
} else {
|
|
||||||
finishAction()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRSView(state.viewState) { viewModel.onEvent(it) }
|
HRSView(state) { viewModel.onEvent(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package no.nordicsemi.android.hrs.view
|
package no.nordicsemi.android.hrs.view
|
||||||
|
|
||||||
sealed class HRSScreenViewEvent
|
internal sealed class HRSScreenViewEvent
|
||||||
|
|
||||||
object DisconnectEvent : HRSScreenViewEvent()
|
internal object DisconnectEvent : HRSScreenViewEvent()
|
||||||
|
|
||||||
|
internal object NavigateUpEvent : HRSScreenViewEvent()
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ package no.nordicsemi.android.hrs.view
|
|||||||
|
|
||||||
import no.nordicsemi.android.hrs.data.HRSData
|
import no.nordicsemi.android.hrs.data.HRSData
|
||||||
|
|
||||||
internal data class HRSState(
|
|
||||||
val viewState: HRSViewState,
|
|
||||||
val isActive: Boolean = true
|
|
||||||
)
|
|
||||||
|
|
||||||
internal sealed class HRSViewState
|
internal sealed class HRSViewState
|
||||||
|
|
||||||
internal object LoadingState : HRSViewState()
|
internal object LoadingState : HRSViewState()
|
||||||
|
|||||||
@@ -5,33 +5,47 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import no.nordicsemi.android.hrs.data.HRSRepository
|
import no.nordicsemi.android.hrs.data.HRSRepository
|
||||||
import no.nordicsemi.android.hrs.view.DisconnectEvent
|
import no.nordicsemi.android.hrs.view.DisconnectEvent
|
||||||
import no.nordicsemi.android.hrs.view.DisplayDataState
|
import no.nordicsemi.android.hrs.view.DisplayDataState
|
||||||
import no.nordicsemi.android.hrs.view.HRSScreenViewEvent
|
import no.nordicsemi.android.hrs.view.HRSScreenViewEvent
|
||||||
import no.nordicsemi.android.hrs.view.HRSState
|
|
||||||
import no.nordicsemi.android.hrs.view.LoadingState
|
import no.nordicsemi.android.hrs.view.LoadingState
|
||||||
|
import no.nordicsemi.android.hrs.view.NavigateUpEvent
|
||||||
|
import no.nordicsemi.android.navigation.NavigationManager
|
||||||
import no.nordicsemi.android.service.BleManagerStatus
|
import no.nordicsemi.android.service.BleManagerStatus
|
||||||
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
internal class HRSViewModel @Inject constructor(
|
internal class HRSViewModel @Inject constructor(
|
||||||
private val repository: HRSRepository
|
private val repository: HRSRepository,
|
||||||
|
private val navigationManager: NavigationManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val state = repository.data.combine(repository.status) { data, status ->
|
val state = repository.data.combine(repository.status) { data, status ->
|
||||||
when (status) {
|
when (status) {
|
||||||
BleManagerStatus.CONNECTING -> HRSState(LoadingState)
|
BleManagerStatus.CONNECTING -> LoadingState
|
||||||
BleManagerStatus.OK -> HRSState(DisplayDataState(data))
|
BleManagerStatus.OK,
|
||||||
BleManagerStatus.DISCONNECTED -> HRSState(DisplayDataState(data), false)
|
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
|
||||||
}
|
}
|
||||||
}.stateIn(viewModelScope, SharingStarted.Lazily, HRSState(LoadingState))
|
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
|
||||||
|
|
||||||
|
init {
|
||||||
|
repository.status.onEach {
|
||||||
|
if (it == BleManagerStatus.DISCONNECTED) {
|
||||||
|
navigationManager.navigateUp()
|
||||||
|
}
|
||||||
|
}.launchIn(viewModelScope)
|
||||||
|
}
|
||||||
|
|
||||||
fun onEvent(event: HRSScreenViewEvent) {
|
fun onEvent(event: HRSScreenViewEvent) {
|
||||||
(event as? DisconnectEvent)?.let {
|
when (event) {
|
||||||
onDisconnectButtonClick()
|
DisconnectEvent -> onDisconnectButtonClick()
|
||||||
}
|
NavigateUpEvent -> navigationManager.navigateUp()
|
||||||
|
}.exhaustive
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onDisconnectButtonClick() {
|
private fun onDisconnectButtonClick() {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation libs.nordic.log
|
implementation libs.nordic.log
|
||||||
implementation libs.nordic.theme
|
implementation libs.nordic.theme
|
||||||
|
implementation libs.nordic.navigation
|
||||||
|
|
||||||
implementation libs.bundles.compose
|
implementation libs.bundles.compose
|
||||||
implementation libs.androidx.core
|
implementation libs.androidx.core
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import no.nordicsemi.android.hts.data.HTSRepository
|
|||||||
import no.nordicsemi.android.service.BatteryManager
|
import no.nordicsemi.android.service.BatteryManager
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
val HT_SERVICE_UUID: UUID = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb")
|
val HTS_SERVICE_UUID: UUID = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb")
|
||||||
private val HT_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb")
|
private val HT_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,7 +81,7 @@ internal class HTSManager internal constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
|
override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
|
||||||
val service = gatt.getService(HT_SERVICE_UUID)
|
val service = gatt.getService(HTS_SERVICE_UUID)
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
htCharacteristic = service.getCharacteristic(HT_MEASUREMENT_CHARACTERISTIC_UUID)
|
htCharacteristic = service.getCharacteristic(HT_MEASUREMENT_CHARACTERISTIC_UUID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
|
|||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HTSScreen(finishAction: () -> Unit) {
|
fun HTSScreen() {
|
||||||
val viewModel: HTSViewModel = hiltViewModel()
|
val viewModel: HTSViewModel = hiltViewModel()
|
||||||
val state = viewModel.state.collectAsState().value
|
val state = viewModel.state.collectAsState().value
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
LaunchedEffect(state.isActive) {
|
LaunchedEffect(Unit) {
|
||||||
if (state.isActive) {
|
val intent = Intent(context, HTSService::class.java)
|
||||||
val intent = Intent(context, HTSService::class.java)
|
context.startService(intent)
|
||||||
context.startService(intent)
|
|
||||||
} else {
|
|
||||||
finishAction()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HTSView(state.viewState) { viewModel.onEvent(it) }
|
HTSView(state) { viewModel.onEvent(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ package no.nordicsemi.android.hts.view
|
|||||||
|
|
||||||
import no.nordicsemi.android.hts.data.HTSData
|
import no.nordicsemi.android.hts.data.HTSData
|
||||||
|
|
||||||
internal data class HTSState(
|
|
||||||
val viewState: HTSViewState,
|
|
||||||
val isActive: Boolean = true
|
|
||||||
)
|
|
||||||
|
|
||||||
internal sealed class HTSViewState
|
internal sealed class HTSViewState
|
||||||
|
|
||||||
internal object LoadingState : HTSViewState()
|
internal object LoadingState : HTSViewState()
|
||||||
|
|||||||
@@ -5,30 +5,41 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import no.nordicsemi.android.hts.data.HTSRepository
|
import no.nordicsemi.android.hts.data.HTSRepository
|
||||||
import no.nordicsemi.android.hts.view.DisconnectEvent
|
import no.nordicsemi.android.hts.view.DisconnectEvent
|
||||||
import no.nordicsemi.android.hts.view.DisplayDataState
|
import no.nordicsemi.android.hts.view.DisplayDataState
|
||||||
import no.nordicsemi.android.hts.view.HTSScreenViewEvent
|
import no.nordicsemi.android.hts.view.HTSScreenViewEvent
|
||||||
import no.nordicsemi.android.hts.view.HTSState
|
|
||||||
import no.nordicsemi.android.hts.view.LoadingState
|
import no.nordicsemi.android.hts.view.LoadingState
|
||||||
import no.nordicsemi.android.hts.view.OnTemperatureUnitSelected
|
import no.nordicsemi.android.hts.view.OnTemperatureUnitSelected
|
||||||
|
import no.nordicsemi.android.navigation.NavigationManager
|
||||||
import no.nordicsemi.android.service.BleManagerStatus
|
import no.nordicsemi.android.service.BleManagerStatus
|
||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
internal class HTSViewModel @Inject constructor(
|
internal class HTSViewModel @Inject constructor(
|
||||||
private val repository: HTSRepository
|
private val repository: HTSRepository,
|
||||||
|
private val navigationManager: NavigationManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val state = repository.data.combine(repository.status) { data, status ->
|
val state = repository.data.combine(repository.status) { data, status ->
|
||||||
when (status) {
|
when (status) {
|
||||||
BleManagerStatus.CONNECTING -> HTSState(LoadingState)
|
BleManagerStatus.CONNECTING -> LoadingState
|
||||||
BleManagerStatus.OK -> HTSState(DisplayDataState(data))
|
BleManagerStatus.OK,
|
||||||
BleManagerStatus.DISCONNECTED -> HTSState(DisplayDataState(data), false)
|
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
|
||||||
}
|
}
|
||||||
}.stateIn(viewModelScope, SharingStarted.Lazily, HTSState(LoadingState))
|
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
|
||||||
|
|
||||||
|
init {
|
||||||
|
repository.status.onEach {
|
||||||
|
if (it == BleManagerStatus.DISCONNECTED) {
|
||||||
|
navigationManager.navigateUp()
|
||||||
|
}
|
||||||
|
}.launchIn(viewModelScope)
|
||||||
|
}
|
||||||
|
|
||||||
fun onEvent(event: HTSScreenViewEvent) {
|
fun onEvent(event: HTSScreenViewEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ dependencies {
|
|||||||
implementation libs.nordic.ble.common
|
implementation libs.nordic.ble.common
|
||||||
|
|
||||||
implementation libs.nordic.log
|
implementation libs.nordic.log
|
||||||
|
implementation libs.nordic.navigation
|
||||||
|
|
||||||
implementation libs.bundles.compose
|
implementation libs.bundles.compose
|
||||||
implementation libs.androidx.core
|
implementation libs.androidx.core
|
||||||
|
|||||||
@@ -17,21 +17,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
|
|||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PRXScreen(finishAction: () -> Unit) {
|
fun PRXScreen() {
|
||||||
val viewModel: PRXViewModel = hiltViewModel()
|
val viewModel: PRXViewModel = hiltViewModel()
|
||||||
val state = viewModel.state.collectAsState().value
|
val state = viewModel.state.collectAsState().value
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
LaunchedEffect(state.isActive) {
|
LaunchedEffect(Unit) {
|
||||||
if (state.isActive) {
|
val intent = Intent(context, PRXService::class.java)
|
||||||
val intent = Intent(context, PRXService::class.java)
|
context.startService(intent)
|
||||||
context.startService(intent)
|
|
||||||
} else {
|
|
||||||
finishAction()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRXView(state.viewState) { viewModel.onEvent(it) }
|
PRXView(state) { viewModel.onEvent(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ package no.nordicsemi.android.prx.view
|
|||||||
|
|
||||||
import no.nordicsemi.android.prx.data.PRXData
|
import no.nordicsemi.android.prx.data.PRXData
|
||||||
|
|
||||||
internal data class PRXState(
|
|
||||||
val viewState: PRXViewState,
|
|
||||||
val isActive: Boolean = true
|
|
||||||
)
|
|
||||||
|
|
||||||
internal sealed class PRXViewState
|
internal sealed class PRXViewState
|
||||||
|
|
||||||
internal object LoadingState : PRXViewState()
|
internal object LoadingState : PRXViewState()
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import no.nordicsemi.android.navigation.NavigationManager
|
||||||
import no.nordicsemi.android.prx.data.DisableAlarm
|
import no.nordicsemi.android.prx.data.DisableAlarm
|
||||||
import no.nordicsemi.android.prx.data.Disconnect
|
import no.nordicsemi.android.prx.data.Disconnect
|
||||||
import no.nordicsemi.android.prx.data.EnableAlarm
|
import no.nordicsemi.android.prx.data.EnableAlarm
|
||||||
@@ -14,7 +17,6 @@ import no.nordicsemi.android.prx.view.DisconnectEvent
|
|||||||
import no.nordicsemi.android.prx.view.DisplayDataState
|
import no.nordicsemi.android.prx.view.DisplayDataState
|
||||||
import no.nordicsemi.android.prx.view.LoadingState
|
import no.nordicsemi.android.prx.view.LoadingState
|
||||||
import no.nordicsemi.android.prx.view.PRXScreenViewEvent
|
import no.nordicsemi.android.prx.view.PRXScreenViewEvent
|
||||||
import no.nordicsemi.android.prx.view.PRXState
|
|
||||||
import no.nordicsemi.android.prx.view.TurnOffAlert
|
import no.nordicsemi.android.prx.view.TurnOffAlert
|
||||||
import no.nordicsemi.android.prx.view.TurnOnAlert
|
import no.nordicsemi.android.prx.view.TurnOnAlert
|
||||||
import no.nordicsemi.android.service.BleManagerStatus
|
import no.nordicsemi.android.service.BleManagerStatus
|
||||||
@@ -23,16 +25,25 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
internal class PRXViewModel @Inject constructor(
|
internal class PRXViewModel @Inject constructor(
|
||||||
private val repository: PRXRepository
|
private val repository: PRXRepository,
|
||||||
|
private val navigationManager: NavigationManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val state = repository.data.combine(repository.status) { data, status ->
|
val state = repository.data.combine(repository.status) { data, status ->
|
||||||
when (status) {
|
when (status) {
|
||||||
BleManagerStatus.CONNECTING -> PRXState(LoadingState)
|
BleManagerStatus.CONNECTING -> LoadingState
|
||||||
BleManagerStatus.OK -> PRXState(DisplayDataState(data))
|
BleManagerStatus.OK,
|
||||||
BleManagerStatus.DISCONNECTED -> PRXState(DisplayDataState(data), false)
|
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
|
||||||
}
|
}
|
||||||
}.stateIn(viewModelScope, SharingStarted.Lazily, PRXState(LoadingState))
|
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
|
||||||
|
|
||||||
|
init {
|
||||||
|
repository.status.onEach {
|
||||||
|
if (it == BleManagerStatus.DISCONNECTED) {
|
||||||
|
navigationManager.navigateUp()
|
||||||
|
}
|
||||||
|
}.launchIn(viewModelScope)
|
||||||
|
}
|
||||||
|
|
||||||
fun onEvent(event: PRXScreenViewEvent) {
|
fun onEvent(event: PRXScreenViewEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ dependencies {
|
|||||||
implementation libs.nordic.ble.common
|
implementation libs.nordic.ble.common
|
||||||
|
|
||||||
implementation libs.nordic.log
|
implementation libs.nordic.log
|
||||||
|
implementation libs.nordic.navigation
|
||||||
|
|
||||||
implementation libs.bundles.compose
|
implementation libs.bundles.compose
|
||||||
implementation libs.androidx.core
|
implementation libs.androidx.core
|
||||||
|
|||||||
@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
|
|||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RSCSScreen(finishAction: () -> Unit) {
|
fun RSCSScreen() {
|
||||||
val viewModel: RSCSViewModel = hiltViewModel()
|
val viewModel: RSCSViewModel = hiltViewModel()
|
||||||
val state = viewModel.state.collectAsState().value
|
val state = viewModel.state.collectAsState().value
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
LaunchedEffect(state.isActive) {
|
LaunchedEffect(Unit) {
|
||||||
if (state.isActive) {
|
val intent = Intent(context, RSCSService::class.java)
|
||||||
val intent = Intent(context, RSCSService::class.java)
|
context.startService(intent)
|
||||||
context.startService(intent)
|
|
||||||
} else {
|
|
||||||
finishAction()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RSCSView(state.viewState) { viewModel.onEvent(it) }
|
RSCSView(state) { viewModel.onEvent(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ package no.nordicsemi.android.rscs.view
|
|||||||
|
|
||||||
import no.nordicsemi.android.rscs.data.RSCSData
|
import no.nordicsemi.android.rscs.data.RSCSData
|
||||||
|
|
||||||
internal data class RSCSState(
|
|
||||||
val viewState: RSCSViewState,
|
|
||||||
val isActive: Boolean = true
|
|
||||||
)
|
|
||||||
|
|
||||||
internal sealed class RSCSViewState
|
internal sealed class RSCSViewState
|
||||||
|
|
||||||
internal object LoadingState : RSCSViewState()
|
internal object LoadingState : RSCSViewState()
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import no.nordicsemi.android.navigation.NavigationManager
|
||||||
import no.nordicsemi.android.rscs.data.RSCSRepository
|
import no.nordicsemi.android.rscs.data.RSCSRepository
|
||||||
import no.nordicsemi.android.rscs.view.DisconnectEvent
|
import no.nordicsemi.android.rscs.view.DisconnectEvent
|
||||||
import no.nordicsemi.android.rscs.view.DisplayDataState
|
import no.nordicsemi.android.rscs.view.DisplayDataState
|
||||||
import no.nordicsemi.android.rscs.view.LoadingState
|
import no.nordicsemi.android.rscs.view.LoadingState
|
||||||
import no.nordicsemi.android.rscs.view.RSCSState
|
|
||||||
import no.nordicsemi.android.rscs.view.RSCScreenViewEvent
|
import no.nordicsemi.android.rscs.view.RSCScreenViewEvent
|
||||||
import no.nordicsemi.android.service.BleManagerStatus
|
import no.nordicsemi.android.service.BleManagerStatus
|
||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
@@ -18,16 +20,25 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
internal class RSCSViewModel @Inject constructor(
|
internal class RSCSViewModel @Inject constructor(
|
||||||
private val repository: RSCSRepository
|
private val repository: RSCSRepository,
|
||||||
|
private val navigationManager: NavigationManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val state = repository.data.combine(repository.status) { data, status ->
|
val state = repository.data.combine(repository.status) { data, status ->
|
||||||
when (status) {
|
when (status) {
|
||||||
BleManagerStatus.CONNECTING -> RSCSState(LoadingState)
|
BleManagerStatus.CONNECTING -> LoadingState
|
||||||
BleManagerStatus.OK -> RSCSState(DisplayDataState(data))
|
BleManagerStatus.OK,
|
||||||
BleManagerStatus.DISCONNECTED -> RSCSState(DisplayDataState(data), false)
|
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
|
||||||
}
|
}
|
||||||
}.stateIn(viewModelScope, SharingStarted.Lazily, RSCSState(LoadingState))
|
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
|
||||||
|
|
||||||
|
init {
|
||||||
|
repository.status.onEach {
|
||||||
|
if (it == BleManagerStatus.DISCONNECTED) {
|
||||||
|
navigationManager.navigateUp()
|
||||||
|
}
|
||||||
|
}.launchIn(viewModelScope)
|
||||||
|
}
|
||||||
|
|
||||||
fun onEvent(event: RSCScreenViewEvent) {
|
fun onEvent(event: RSCScreenViewEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation libs.nordic.log
|
implementation libs.nordic.log
|
||||||
implementation libs.nordic.theme
|
implementation libs.nordic.theme
|
||||||
|
implementation libs.nordic.navigation
|
||||||
|
|
||||||
implementation libs.bundles.compose
|
implementation libs.bundles.compose
|
||||||
implementation libs.androidx.core
|
implementation libs.androidx.core
|
||||||
|
|||||||
@@ -16,21 +16,17 @@ import no.nordicsemi.android.uart.viewmodel.UARTViewModel
|
|||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UARTScreen(finishAction: () -> Unit) {
|
fun UARTScreen() {
|
||||||
val viewModel: UARTViewModel = hiltViewModel()
|
val viewModel: UARTViewModel = hiltViewModel()
|
||||||
val state = viewModel.state.collectAsState().value
|
val state = viewModel.state.collectAsState().value
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
LaunchedEffect(state.isActive) {
|
LaunchedEffect(Unit) {
|
||||||
if (state.isActive) {
|
val intent = Intent(context, UARTService::class.java)
|
||||||
val intent = Intent(context, UARTService::class.java)
|
context.startService(intent)
|
||||||
context.startService(intent)
|
|
||||||
} else if (!state.isActive) {
|
|
||||||
finishAction()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UARTView(state.viewState) { viewModel.onEvent(it) }
|
UARTView(state) { viewModel.onEvent(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ package no.nordicsemi.android.uart.view
|
|||||||
|
|
||||||
import no.nordicsemi.android.uart.data.UARTData
|
import no.nordicsemi.android.uart.data.UARTData
|
||||||
|
|
||||||
internal data class UARTState(
|
|
||||||
val viewState: UARTViewState,
|
|
||||||
val isActive: Boolean = true
|
|
||||||
)
|
|
||||||
|
|
||||||
internal sealed class UARTViewState
|
internal sealed class UARTViewState
|
||||||
|
|
||||||
internal object LoadingState : UARTViewState()
|
internal object LoadingState : UARTViewState()
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import no.nordicsemi.android.navigation.NavigationManager
|
||||||
import no.nordicsemi.android.service.BleManagerStatus
|
import no.nordicsemi.android.service.BleManagerStatus
|
||||||
import no.nordicsemi.android.uart.data.DisconnectCommand
|
import no.nordicsemi.android.uart.data.DisconnectCommand
|
||||||
import no.nordicsemi.android.uart.data.SendTextCommand
|
import no.nordicsemi.android.uart.data.SendTextCommand
|
||||||
@@ -16,23 +19,31 @@ import no.nordicsemi.android.uart.view.OnCreateMacro
|
|||||||
import no.nordicsemi.android.uart.view.OnDeleteMacro
|
import no.nordicsemi.android.uart.view.OnDeleteMacro
|
||||||
import no.nordicsemi.android.uart.view.OnDisconnectButtonClick
|
import no.nordicsemi.android.uart.view.OnDisconnectButtonClick
|
||||||
import no.nordicsemi.android.uart.view.OnRunMacro
|
import no.nordicsemi.android.uart.view.OnRunMacro
|
||||||
import no.nordicsemi.android.uart.view.UARTState
|
|
||||||
import no.nordicsemi.android.uart.view.UARTViewEvent
|
import no.nordicsemi.android.uart.view.UARTViewEvent
|
||||||
import no.nordicsemi.android.utils.exhaustive
|
import no.nordicsemi.android.utils.exhaustive
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
internal class UARTViewModel @Inject constructor(
|
internal class UARTViewModel @Inject constructor(
|
||||||
private val repository: UARTRepository
|
private val repository: UARTRepository,
|
||||||
|
private val navigationManager: NavigationManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val state = repository.data.combine(repository.status) { data, status ->
|
val state = repository.data.combine(repository.status) { data, status ->
|
||||||
when (status) {
|
when (status) {
|
||||||
BleManagerStatus.CONNECTING -> UARTState(LoadingState)
|
BleManagerStatus.CONNECTING -> LoadingState
|
||||||
BleManagerStatus.OK -> UARTState(DisplayDataState(data))
|
BleManagerStatus.OK,
|
||||||
BleManagerStatus.DISCONNECTED -> UARTState(DisplayDataState(data), false)
|
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
|
||||||
}
|
}
|
||||||
}.stateIn(viewModelScope, SharingStarted.Lazily, UARTState(LoadingState))
|
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
|
||||||
|
|
||||||
|
init {
|
||||||
|
repository.status.onEach {
|
||||||
|
if (it == BleManagerStatus.DISCONNECTED) {
|
||||||
|
navigationManager.navigateUp()
|
||||||
|
}
|
||||||
|
}.launchIn(viewModelScope)
|
||||||
|
}
|
||||||
|
|
||||||
fun onEvent(event: UARTViewEvent) {
|
fun onEvent(event: UARTViewEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ dependencyResolutionManagement {
|
|||||||
|
|
||||||
versionCatalogs {
|
versionCatalogs {
|
||||||
libs {
|
libs {
|
||||||
|
alias('nordic-navigation').to('no.nordicsemi.android.common:navigation:1.0.0')
|
||||||
alias('nordic-theme').to('no.nordicsemi.android.common:theme:1.0.0')
|
alias('nordic-theme').to('no.nordicsemi.android.common:theme:1.0.0')
|
||||||
alias('nordic-ble-common').to('no.nordicsemi.android:ble-common:2.3.1')
|
alias('nordic-ble-common').to('no.nordicsemi.android:ble-common:2.3.1')
|
||||||
alias('nordic-log').to('no.nordicsemi.android:log:2.3.0')
|
alias('nordic-log').to('no.nordicsemi.android:log:2.3.0')
|
||||||
@@ -76,11 +77,13 @@ include ':app'
|
|||||||
include ':profile_bps'
|
include ':profile_bps'
|
||||||
include ':profile_cgms'
|
include ':profile_cgms'
|
||||||
include ':profile_csc'
|
include ':profile_csc'
|
||||||
|
include ':profile_dfu'
|
||||||
include ':profile_gls'
|
include ':profile_gls'
|
||||||
include ':profile_hrs'
|
include ':profile_hrs'
|
||||||
include ':profile_hts'
|
include ':profile_hts'
|
||||||
include ':profile_prx'
|
include ':profile_prx'
|
||||||
include ':profile_rscs'
|
include ':profile_rscs'
|
||||||
|
include ':profile_uart'
|
||||||
|
|
||||||
include ':lib_service'
|
include ':lib_service'
|
||||||
include ':lib_theme'
|
include ':lib_theme'
|
||||||
@@ -89,13 +92,3 @@ include ':lib_utils'
|
|||||||
if (file('../Android-Common-Libraries').exists()) {
|
if (file('../Android-Common-Libraries').exists()) {
|
||||||
includeBuild('../Android-Common-Libraries')
|
includeBuild('../Android-Common-Libraries')
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (file('../Android-BLE-Library').exists()) {
|
|
||||||
// includeBuild('../Android-BLE-Library')
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//if (file('../Android-Scanner-Compat-Library').exists()) {
|
|
||||||
// includeBuild('../Android-Scanner-Compat-Library')
|
|
||||||
//}
|
|
||||||
include ':profile_uart'
|
|
||||||
include ':profile_dfu'
|
|
||||||
|
|||||||
Reference in New Issue
Block a user