Switch to new navigation.

This commit is contained in:
Sylwester Zieliński
2022-01-19 14:28:42 +01:00
parent 2c304e80f6
commit 2dd3e4bec3
50 changed files with 295 additions and 424 deletions

View File

@@ -71,6 +71,7 @@ dependencies {
implementation libs.nordic.ble.common
implementation libs.nordic.ui.scanner
implementation libs.nordic.navigation
implementation libs.bundles.koin
implementation libs.bundles.hilt

View File

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

View File

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

View File

@@ -18,10 +18,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import no.nordicsemi.android.theme.view.CloseIconAppBar
@Composable
fun HomeView(viewModel: HomeViewModel) {
fun HomeScreen() {
val viewModel: HomeViewModel = hiltViewModel()
Column {
val context = LocalContext.current
CloseIconAppBar(stringResource(id = R.string.app_name)) {
@@ -43,12 +46,12 @@ fun HomeView(viewModel: HomeViewModel) {
DoubleSection(
leftView = {
FeatureButton(R.drawable.ic_csc, R.string.csc_module, R.string.csc_module_full) {
viewModel.openProfile(Profile.CSC)
viewModel.openProfile(ProfileDestination.CSC)
}
},
rightView = {
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(
leftView = {
FeatureButton(R.drawable.ic_gls, R.string.gls_module, R.string.gls_module_full) {
viewModel.openProfile(Profile.GLS)
viewModel.openProfile(ProfileDestination.GLS)
}
},
rightView = {
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(
leftView = {
FeatureButton(R.drawable.ic_bps, R.string.bps_module, R.string.bps_module_full) {
viewModel.openProfile(Profile.BPS)
viewModel.openProfile(ProfileDestination.BPS)
}
},
rightView = {
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(
leftView = {
FeatureButton(R.drawable.ic_prx, R.string.prx_module, R.string.prx_module_full) {
viewModel.openProfile(Profile.PRX)
viewModel.openProfile(ProfileDestination.PRX)
}
},
rightView = {
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))
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))

View File

@@ -2,50 +2,22 @@ package no.nordicsemi.android.nrftoolbox
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import no.nordicsemi.android.navigation.ForwardDestination
import no.nordicsemi.android.navigation.NavigationManager
import no.nordicsemi.android.navigation.UUIDArgument
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
@HiltViewModel
class HomeViewModel @Inject constructor(
private val deviceHolder: SelectedBluetoothDeviceHolder
private val deviceHolder: SelectedBluetoothDeviceHolder,
private val navigationManager: NavigationManager
) : ViewModel() {
private val _destination = MutableStateFlow<NavDestination>(HomeDestination)
val destination = _destination.asStateFlow()
var profile: Profile? = null //to pass argument between nav destinations
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)
fun openProfile(destination: ProfileDestination) {
navigationManager.navigateTo(
ForwardDestination(destination.destination.id),
UUIDArgument(destination.uuid)
)
}
}

View File

@@ -9,6 +9,8 @@ import androidx.compose.ui.Modifier
import dagger.hilt.android.AndroidEntryPoint
import no.nordicsemi.android.material.you.NordicActivity
import no.nordicsemi.android.material.you.NordicTheme
import no.nordicsemi.android.navigation.NavigationView
import no.nordicsemi.ui.scanner.ScannerDestinations
@AndroidEntryPoint
class MainActivity : NordicActivity() {
@@ -22,7 +24,9 @@ class MainActivity : NordicActivity() {
color = MaterialTheme.colorScheme.surface,
modifier = Modifier.fillMaxSize()
) {
HomeScreen()
NavigationView(
HomeDestinations + ProfileDestinations + ScannerDestinations
)
}
}
}

View File

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

View File

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

View File

@@ -7,6 +7,7 @@ dependencies {
implementation project(":lib_utils")
implementation libs.nordic.ble.common
implementation libs.nordic.navigation
implementation libs.nordic.log
implementation libs.nordic.ui.scanner

View File

@@ -13,19 +13,15 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
import no.nordicsemi.android.utils.exhaustive
@Composable
fun BPSScreen(finishAction: () -> Unit) {
fun BPSScreen() {
val viewModel: BPSViewModel = hiltViewModel()
val state = viewModel.state.collectAsState().value
LaunchedEffect(state.isActive) {
if (state.isActive) {
LaunchedEffect(Unit) {
viewModel.connectDevice()
} else {
finishAction()
}
}
BPSView(state.viewState) { viewModel.onEvent(it) }
BPSView(state) { viewModel.onEvent(it) }
}
@Composable

View File

@@ -2,11 +2,6 @@ package no.nordicsemi.android.bps.view
import no.nordicsemi.android.bps.data.BPSData
internal data class BPSState(
val viewState: BPSViewState,
val isActive: Boolean = true
)
internal sealed class BPSViewState
internal object LoadingState : BPSViewState()

View File

@@ -6,14 +6,16 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import no.nordicsemi.android.bps.data.BPSRepository
import no.nordicsemi.android.bps.repository.BPSManager
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.DisplayDataState
import no.nordicsemi.android.bps.view.LoadingState
import no.nordicsemi.android.navigation.NavigationManager
import no.nordicsemi.android.service.BleManagerStatus
import no.nordicsemi.android.service.ConnectionObserverAdapter
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
@@ -24,16 +26,17 @@ import javax.inject.Inject
internal class BPSViewModel @Inject constructor(
private val bpsManager: BPSManager,
private val deviceHolder: SelectedBluetoothDeviceHolder,
private val repository: BPSRepository
private val repository: BPSRepository,
private val navigationManager: NavigationManager
) : ViewModel() {
val state = repository.data.combine(repository.status) { data, status ->
when (status) {
BleManagerStatus.CONNECTING -> BPSState(LoadingState)
BleManagerStatus.OK -> BPSState(DisplayDataState(data))
BleManagerStatus.DISCONNECTED -> BPSState(DisplayDataState(data), false)
BleManagerStatus.CONNECTING -> LoadingState
BleManagerStatus.OK,
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, BPSState(LoadingState))
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
init {
bpsManager.setConnectionObserver(object : ConnectionObserverAdapter() {
@@ -52,6 +55,12 @@ internal class BPSViewModel @Inject constructor(
repository.setNewStatus(BleManagerStatus.DISCONNECTED)
}
})
repository.status.onEach {
if (it == BleManagerStatus.DISCONNECTED) {
navigationManager.navigateUp()
}
}.launchIn(viewModelScope)
}
fun onEvent(event: BPSScreenViewEvent) {

View File

@@ -10,6 +10,7 @@ dependencies {
implementation libs.nordic.log
implementation libs.nordic.theme
implementation libs.nordic.navigation
implementation libs.bundles.compose
implementation libs.androidx.core

View File

@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
import no.nordicsemi.android.utils.exhaustive
@Composable
fun CGMScreen(finishAction: () -> Unit) {
fun CGMScreen() {
val viewModel: CGMScreenViewModel = hiltViewModel()
val state = viewModel.state.collectAsState().value
val context = LocalContext.current
LaunchedEffect(state.isActive) {
if (state.isActive) {
LaunchedEffect(Unit) {
val intent = Intent(context, CGMService::class.java)
context.startService(intent)
} else if (!state.isActive) {
finishAction()
}
}
CGMView(state.viewState) {
CGMView(state) {
viewModel.onEvent(it)
}
}

View File

@@ -2,11 +2,6 @@ package no.nordicsemi.android.cgms.view
import no.nordicsemi.android.cgms.data.CGMData
internal data class CGMState(
val viewState: CGMViewState,
val isActive: Boolean = true
)
internal sealed class CGMViewState
internal object LoadingState : CGMViewState()

View File

@@ -5,31 +5,42 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import no.nordicsemi.android.cgms.data.CGMRepository
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.DisconnectEvent
import no.nordicsemi.android.cgms.view.DisplayDataState
import no.nordicsemi.android.cgms.view.LoadingState
import no.nordicsemi.android.cgms.view.OnWorkingModeSelected
import no.nordicsemi.android.navigation.NavigationManager
import no.nordicsemi.android.service.BleManagerStatus
import no.nordicsemi.android.utils.exhaustive
import javax.inject.Inject
@HiltViewModel
internal class CGMScreenViewModel @Inject constructor(
private val repository: CGMRepository
private val repository: CGMRepository,
private val navigationManager: NavigationManager
) : ViewModel() {
val state = repository.data.combine(repository.status) { data, status ->
when (status) {
BleManagerStatus.CONNECTING -> CGMState(LoadingState)
BleManagerStatus.OK -> CGMState(DisplayDataState(data))
BleManagerStatus.DISCONNECTED -> CGMState(DisplayDataState(data), false)
BleManagerStatus.CONNECTING -> LoadingState
BleManagerStatus.OK,
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
init {
repository.status.onEach {
if (it == BleManagerStatus.DISCONNECTED) {
navigationManager.navigateUp()
}
}.launchIn(viewModelScope)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, CGMState(LoadingState))
fun onEvent(event: CGMViewEvent) {
when (event) {

View File

@@ -10,6 +10,7 @@ dependencies {
implementation libs.nordic.log
implementation libs.nordic.theme
implementation libs.nordic.navigation
implementation libs.bundles.compose
implementation libs.androidx.core

View File

@@ -35,7 +35,7 @@ import no.nordicsemi.android.service.BatteryManager
import java.util.*
/** 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. */
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 {
val service = gatt.getService(CYCLING_SPEED_AND_CADENCE_SERVICE_UUID)
val service = gatt.getService(CSC_SERVICE_UUID)
if (service != null) {
cscMeasurementCharacteristic = service.getCharacteristic(
CSC_MEASUREMENT_CHARACTERISTIC_UUID

View File

@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
import no.nordicsemi.android.utils.exhaustive
@Composable
fun CSCScreen(finishAction: () -> Unit) {
fun CSCScreen() {
val viewModel: CSCViewModel = hiltViewModel()
val state = viewModel.state.collectAsState().value
val context = LocalContext.current
LaunchedEffect(state.isActive) {
if (state.isActive) {
LaunchedEffect(Unit) {
val intent = Intent(context, CSCService::class.java)
context.startService(intent)
} else {
finishAction()
}
}
CSCView(state.viewState) { viewModel.onEvent(it) }
CSCView(state) { viewModel.onEvent(it) }
}
@Composable

View File

@@ -2,11 +2,6 @@ package no.nordicsemi.android.csc.view
import no.nordicsemi.android.csc.data.CSCData
internal data class CSCState(
val viewState: CSCViewState,
val isActive: Boolean = true
)
internal sealed class CSCViewState
internal object LoadingState : CSCViewState()

View File

@@ -5,33 +5,44 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import no.nordicsemi.android.csc.data.CSCRepository
import no.nordicsemi.android.csc.data.DisconnectCommand
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.DisplayDataState
import no.nordicsemi.android.csc.view.LoadingState
import no.nordicsemi.android.csc.view.OnDisconnectButtonClick
import no.nordicsemi.android.csc.view.OnSelectedSpeedUnitSelected
import no.nordicsemi.android.csc.view.OnWheelSizeSelected
import no.nordicsemi.android.navigation.NavigationManager
import no.nordicsemi.android.service.BleManagerStatus
import no.nordicsemi.android.utils.exhaustive
import javax.inject.Inject
@HiltViewModel
internal class CSCViewModel @Inject constructor(
private val repository: CSCRepository
private val repository: CSCRepository,
private val navigationManager: NavigationManager
) : ViewModel() {
val state = repository.data.combine(repository.status) { data, status ->
when (status) {
BleManagerStatus.CONNECTING -> CSCState(LoadingState)
BleManagerStatus.OK -> CSCState(DisplayDataState(data))
BleManagerStatus.DISCONNECTED -> CSCState(DisplayDataState(data), false)
BleManagerStatus.CONNECTING -> LoadingState
BleManagerStatus.OK,
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
init {
repository.status.onEach {
if (it == BleManagerStatus.DISCONNECTED) {
navigationManager.navigateUp()
}
}.launchIn(viewModelScope)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, CSCState(LoadingState))
fun onEvent(event: CSCViewEvent) {
when (event) {

View File

@@ -10,6 +10,7 @@ dependencies {
implementation libs.nordic.ble.common
implementation libs.nordic.theme
implementation libs.nordic.navigation
implementation libs.nordic.log
implementation libs.nordic.dfu

View File

@@ -11,6 +11,7 @@ dependencies {
implementation libs.nordic.ble.common
implementation libs.nordic.theme
implementation libs.nordic.ui.scanner
implementation libs.nordic.navigation
implementation libs.nordic.log

View File

@@ -2,11 +2,6 @@ package no.nordicsemi.android.gls.view
import no.nordicsemi.android.gls.data.GLSData
internal data class GLSState(
val viewState: GLSViewState,
val isActive: Boolean = true
)
internal sealed class GLSViewState
internal object LoadingState : GLSViewState()

View File

@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
import no.nordicsemi.android.utils.exhaustive
@Composable
fun GLSScreen(finishAction: () -> Unit) {
fun GLSScreen() {
val viewModel: GLSViewModel = hiltViewModel()
val state = viewModel.state.collectAsState().value
Log.d("AAATESTAAA", "$viewModel") //TODO fix screen rotation
LaunchedEffect(state.isActive) {
if (state.isActive) {
LaunchedEffect(Unit) {
viewModel.connectDevice()
} else {
finishAction()
}
}
GLSView(state.viewState) {
GLSView(state) {
viewModel.onEvent(it)
}
}

View File

@@ -6,13 +6,15 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import no.nordicsemi.android.gls.data.GLSRepository
import no.nordicsemi.android.gls.data.WorkingMode
import no.nordicsemi.android.gls.repository.GLSManager
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.navigation.NavigationManager
import no.nordicsemi.android.service.BleManagerStatus
import no.nordicsemi.android.service.ConnectionObserverAdapter
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
@@ -23,16 +25,17 @@ import javax.inject.Inject
internal class GLSViewModel @Inject constructor(
private val glsManager: GLSManager,
private val deviceHolder: SelectedBluetoothDeviceHolder,
private val repository: GLSRepository
private val repository: GLSRepository,
private val navigationManager: NavigationManager
) : ViewModel() {
val state = repository.data.combine(repository.status) { data, status ->
when (status) {
BleManagerStatus.CONNECTING -> GLSState(LoadingState)
BleManagerStatus.OK -> GLSState(DisplayDataState(data))
BleManagerStatus.DISCONNECTED -> GLSState(DisplayDataState(data), false)
BleManagerStatus.CONNECTING -> LoadingState
BleManagerStatus.OK,
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, GLSState(LoadingState))
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
init {
glsManager.setConnectionObserver(object : ConnectionObserverAdapter() {
@@ -51,6 +54,12 @@ internal class GLSViewModel @Inject constructor(
repository.setNewStatus(BleManagerStatus.DISCONNECTED)
}
})
repository.status.onEach {
if (it == BleManagerStatus.DISCONNECTED) {
navigationManager.navigateUp()
}
}.launchIn(viewModelScope)
}
fun onEvent(event: GLSScreenViewEvent) {

View File

@@ -9,6 +9,7 @@ dependencies {
implementation libs.chart
implementation libs.nordic.ble.common
implementation libs.nordic.navigation
implementation libs.nordic.log

View File

@@ -34,7 +34,7 @@ import no.nordicsemi.android.hrs.data.HRSRepository
import no.nordicsemi.android.service.BatteryManager
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 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 {
val service = gatt.getService(HR_SERVICE_UUID)
val service = gatt.getService(HRS_SERVICE_UUID)
if (service != null) {
heartRateCharacteristic = service.getCharacteristic(
HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID
@@ -111,7 +111,7 @@ internal class HRSManager(context: Context, private val dataHolder: HRSRepositor
override fun isOptionalServiceSupported(gatt: BluetoothGatt): Boolean {
super.isOptionalServiceSupported(gatt)
val service = gatt.getService(HR_SERVICE_UUID)
val service = gatt.getService(HRS_SERVICE_UUID)
if (service != null) {
bodySensorLocationCharacteristic = service.getCharacteristic(
BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID

View File

@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
import no.nordicsemi.android.utils.exhaustive
@Composable
fun HRSScreen(finishAction: () -> Unit) {
fun HRSScreen() {
val viewModel: HRSViewModel = hiltViewModel()
val state = viewModel.state.collectAsState().value
val context = LocalContext.current
LaunchedEffect(state.isActive) {
if (state.isActive) {
LaunchedEffect(Unit) {
val intent = Intent(context, HRSService::class.java)
context.startService(intent)
} else {
finishAction()
}
}
HRSView(state.viewState) { viewModel.onEvent(it) }
HRSView(state) { viewModel.onEvent(it) }
}
@Composable

View File

@@ -1,5 +1,7 @@
package no.nordicsemi.android.hrs.view
sealed class HRSScreenViewEvent
internal sealed class HRSScreenViewEvent
object DisconnectEvent : HRSScreenViewEvent()
internal object DisconnectEvent : HRSScreenViewEvent()
internal object NavigateUpEvent : HRSScreenViewEvent()

View File

@@ -2,11 +2,6 @@ package no.nordicsemi.android.hrs.view
import no.nordicsemi.android.hrs.data.HRSData
internal data class HRSState(
val viewState: HRSViewState,
val isActive: Boolean = true
)
internal sealed class HRSViewState
internal object LoadingState : HRSViewState()

View File

@@ -5,33 +5,47 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import no.nordicsemi.android.hrs.data.HRSRepository
import no.nordicsemi.android.hrs.view.DisconnectEvent
import no.nordicsemi.android.hrs.view.DisplayDataState
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.NavigateUpEvent
import no.nordicsemi.android.navigation.NavigationManager
import no.nordicsemi.android.service.BleManagerStatus
import no.nordicsemi.android.utils.exhaustive
import javax.inject.Inject
@HiltViewModel
internal class HRSViewModel @Inject constructor(
private val repository: HRSRepository
private val repository: HRSRepository,
private val navigationManager: NavigationManager
) : ViewModel() {
val state = repository.data.combine(repository.status) { data, status ->
when (status) {
BleManagerStatus.CONNECTING -> HRSState(LoadingState)
BleManagerStatus.OK -> HRSState(DisplayDataState(data))
BleManagerStatus.DISCONNECTED -> HRSState(DisplayDataState(data), false)
BleManagerStatus.CONNECTING -> LoadingState
BleManagerStatus.OK,
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
init {
repository.status.onEach {
if (it == BleManagerStatus.DISCONNECTED) {
navigationManager.navigateUp()
}
}.launchIn(viewModelScope)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, HRSState(LoadingState))
fun onEvent(event: HRSScreenViewEvent) {
(event as? DisconnectEvent)?.let {
onDisconnectButtonClick()
}
when (event) {
DisconnectEvent -> onDisconnectButtonClick()
NavigateUpEvent -> navigationManager.navigateUp()
}.exhaustive
}
private fun onDisconnectButtonClick() {

View File

@@ -10,6 +10,7 @@ dependencies {
implementation libs.nordic.log
implementation libs.nordic.theme
implementation libs.nordic.navigation
implementation libs.bundles.compose
implementation libs.androidx.core

View File

@@ -32,7 +32,7 @@ import no.nordicsemi.android.hts.data.HTSRepository
import no.nordicsemi.android.service.BatteryManager
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")
/**
@@ -81,7 +81,7 @@ internal class HTSManager internal constructor(
}
override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
val service = gatt.getService(HT_SERVICE_UUID)
val service = gatt.getService(HTS_SERVICE_UUID)
if (service != null) {
htCharacteristic = service.getCharacteristic(HT_MEASUREMENT_CHARACTERISTIC_UUID)
}

View File

@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
import no.nordicsemi.android.utils.exhaustive
@Composable
fun HTSScreen(finishAction: () -> Unit) {
fun HTSScreen() {
val viewModel: HTSViewModel = hiltViewModel()
val state = viewModel.state.collectAsState().value
val context = LocalContext.current
LaunchedEffect(state.isActive) {
if (state.isActive) {
LaunchedEffect(Unit) {
val intent = Intent(context, HTSService::class.java)
context.startService(intent)
} else {
finishAction()
}
}
HTSView(state.viewState) { viewModel.onEvent(it) }
HTSView(state) { viewModel.onEvent(it) }
}
@Composable

View File

@@ -2,11 +2,6 @@ package no.nordicsemi.android.hts.view
import no.nordicsemi.android.hts.data.HTSData
internal data class HTSState(
val viewState: HTSViewState,
val isActive: Boolean = true
)
internal sealed class HTSViewState
internal object LoadingState : HTSViewState()

View File

@@ -5,30 +5,41 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import no.nordicsemi.android.hts.data.HTSRepository
import no.nordicsemi.android.hts.view.DisconnectEvent
import no.nordicsemi.android.hts.view.DisplayDataState
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.OnTemperatureUnitSelected
import no.nordicsemi.android.navigation.NavigationManager
import no.nordicsemi.android.service.BleManagerStatus
import no.nordicsemi.android.utils.exhaustive
import javax.inject.Inject
@HiltViewModel
internal class HTSViewModel @Inject constructor(
private val repository: HTSRepository
private val repository: HTSRepository,
private val navigationManager: NavigationManager
) : ViewModel() {
val state = repository.data.combine(repository.status) { data, status ->
when (status) {
BleManagerStatus.CONNECTING -> HTSState(LoadingState)
BleManagerStatus.OK -> HTSState(DisplayDataState(data))
BleManagerStatus.DISCONNECTED -> HTSState(DisplayDataState(data), false)
BleManagerStatus.CONNECTING -> LoadingState
BleManagerStatus.OK,
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
init {
repository.status.onEach {
if (it == BleManagerStatus.DISCONNECTED) {
navigationManager.navigateUp()
}
}.launchIn(viewModelScope)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, HTSState(LoadingState))
fun onEvent(event: HTSScreenViewEvent) {
when (event) {

View File

@@ -9,6 +9,7 @@ dependencies {
implementation libs.nordic.ble.common
implementation libs.nordic.log
implementation libs.nordic.navigation
implementation libs.bundles.compose
implementation libs.androidx.core

View File

@@ -17,21 +17,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
import no.nordicsemi.android.utils.exhaustive
@Composable
fun PRXScreen(finishAction: () -> Unit) {
fun PRXScreen() {
val viewModel: PRXViewModel = hiltViewModel()
val state = viewModel.state.collectAsState().value
val context = LocalContext.current
LaunchedEffect(state.isActive) {
if (state.isActive) {
LaunchedEffect(Unit) {
val intent = Intent(context, PRXService::class.java)
context.startService(intent)
} else {
finishAction()
}
}
PRXView(state.viewState) { viewModel.onEvent(it) }
PRXView(state) { viewModel.onEvent(it) }
}
@Composable

View File

@@ -2,11 +2,6 @@ package no.nordicsemi.android.prx.view
import no.nordicsemi.android.prx.data.PRXData
internal data class PRXState(
val viewState: PRXViewState,
val isActive: Boolean = true
)
internal sealed class PRXViewState
internal object LoadingState : PRXViewState()

View File

@@ -5,7 +5,10 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import no.nordicsemi.android.navigation.NavigationManager
import no.nordicsemi.android.prx.data.DisableAlarm
import no.nordicsemi.android.prx.data.Disconnect
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.LoadingState
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.TurnOnAlert
import no.nordicsemi.android.service.BleManagerStatus
@@ -23,16 +25,25 @@ import javax.inject.Inject
@HiltViewModel
internal class PRXViewModel @Inject constructor(
private val repository: PRXRepository
private val repository: PRXRepository,
private val navigationManager: NavigationManager
) : ViewModel() {
val state = repository.data.combine(repository.status) { data, status ->
when (status) {
BleManagerStatus.CONNECTING -> PRXState(LoadingState)
BleManagerStatus.OK -> PRXState(DisplayDataState(data))
BleManagerStatus.DISCONNECTED -> PRXState(DisplayDataState(data), false)
BleManagerStatus.CONNECTING -> LoadingState
BleManagerStatus.OK,
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
init {
repository.status.onEach {
if (it == BleManagerStatus.DISCONNECTED) {
navigationManager.navigateUp()
}
}.launchIn(viewModelScope)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, PRXState(LoadingState))
fun onEvent(event: PRXScreenViewEvent) {
when (event) {

View File

@@ -9,6 +9,7 @@ dependencies {
implementation libs.nordic.ble.common
implementation libs.nordic.log
implementation libs.nordic.navigation
implementation libs.bundles.compose
implementation libs.androidx.core

View File

@@ -16,21 +16,17 @@ import no.nordicsemi.android.theme.view.DeviceConnectingView
import no.nordicsemi.android.utils.exhaustive
@Composable
fun RSCSScreen(finishAction: () -> Unit) {
fun RSCSScreen() {
val viewModel: RSCSViewModel = hiltViewModel()
val state = viewModel.state.collectAsState().value
val context = LocalContext.current
LaunchedEffect(state.isActive) {
if (state.isActive) {
LaunchedEffect(Unit) {
val intent = Intent(context, RSCSService::class.java)
context.startService(intent)
} else {
finishAction()
}
}
RSCSView(state.viewState) { viewModel.onEvent(it) }
RSCSView(state) { viewModel.onEvent(it) }
}
@Composable

View File

@@ -2,11 +2,6 @@ package no.nordicsemi.android.rscs.view
import no.nordicsemi.android.rscs.data.RSCSData
internal data class RSCSState(
val viewState: RSCSViewState,
val isActive: Boolean = true
)
internal sealed class RSCSViewState
internal object LoadingState : RSCSViewState()

View File

@@ -5,12 +5,14 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import no.nordicsemi.android.navigation.NavigationManager
import no.nordicsemi.android.rscs.data.RSCSRepository
import no.nordicsemi.android.rscs.view.DisconnectEvent
import no.nordicsemi.android.rscs.view.DisplayDataState
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.service.BleManagerStatus
import no.nordicsemi.android.utils.exhaustive
@@ -18,16 +20,25 @@ import javax.inject.Inject
@HiltViewModel
internal class RSCSViewModel @Inject constructor(
private val repository: RSCSRepository
private val repository: RSCSRepository,
private val navigationManager: NavigationManager
) : ViewModel() {
val state = repository.data.combine(repository.status) { data, status ->
when (status) {
BleManagerStatus.CONNECTING -> RSCSState(LoadingState)
BleManagerStatus.OK -> RSCSState(DisplayDataState(data))
BleManagerStatus.DISCONNECTED -> RSCSState(DisplayDataState(data), false)
BleManagerStatus.CONNECTING -> LoadingState
BleManagerStatus.OK,
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
init {
repository.status.onEach {
if (it == BleManagerStatus.DISCONNECTED) {
navigationManager.navigateUp()
}
}.launchIn(viewModelScope)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, RSCSState(LoadingState))
fun onEvent(event: RSCScreenViewEvent) {
when (event) {

View File

@@ -10,6 +10,7 @@ dependencies {
implementation libs.nordic.log
implementation libs.nordic.theme
implementation libs.nordic.navigation
implementation libs.bundles.compose
implementation libs.androidx.core

View File

@@ -16,21 +16,17 @@ import no.nordicsemi.android.uart.viewmodel.UARTViewModel
import no.nordicsemi.android.utils.exhaustive
@Composable
fun UARTScreen(finishAction: () -> Unit) {
fun UARTScreen() {
val viewModel: UARTViewModel = hiltViewModel()
val state = viewModel.state.collectAsState().value
val context = LocalContext.current
LaunchedEffect(state.isActive) {
if (state.isActive) {
LaunchedEffect(Unit) {
val intent = Intent(context, UARTService::class.java)
context.startService(intent)
} else if (!state.isActive) {
finishAction()
}
}
UARTView(state.viewState) { viewModel.onEvent(it) }
UARTView(state) { viewModel.onEvent(it) }
}
@Composable

View File

@@ -2,11 +2,6 @@ package no.nordicsemi.android.uart.view
import no.nordicsemi.android.uart.data.UARTData
internal data class UARTState(
val viewState: UARTViewState,
val isActive: Boolean = true
)
internal sealed class UARTViewState
internal object LoadingState : UARTViewState()

View File

@@ -5,7 +5,10 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import no.nordicsemi.android.navigation.NavigationManager
import no.nordicsemi.android.service.BleManagerStatus
import no.nordicsemi.android.uart.data.DisconnectCommand
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.OnDisconnectButtonClick
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.utils.exhaustive
import javax.inject.Inject
@HiltViewModel
internal class UARTViewModel @Inject constructor(
private val repository: UARTRepository
private val repository: UARTRepository,
private val navigationManager: NavigationManager
) : ViewModel() {
val state = repository.data.combine(repository.status) { data, status ->
when (status) {
BleManagerStatus.CONNECTING -> UARTState(LoadingState)
BleManagerStatus.OK -> UARTState(DisplayDataState(data))
BleManagerStatus.DISCONNECTED -> UARTState(DisplayDataState(data), false)
BleManagerStatus.CONNECTING -> LoadingState
BleManagerStatus.OK,
BleManagerStatus.DISCONNECTED -> DisplayDataState(data)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
init {
repository.status.onEach {
if (it == BleManagerStatus.DISCONNECTED) {
navigationManager.navigateUp()
}
}.launchIn(viewModelScope)
}
}.stateIn(viewModelScope, SharingStarted.Lazily, UARTState(LoadingState))
fun onEvent(event: UARTViewEvent) {
when (event) {

View File

@@ -11,6 +11,7 @@ dependencyResolutionManagement {
versionCatalogs {
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-ble-common').to('no.nordicsemi.android:ble-common:2.3.1')
alias('nordic-log').to('no.nordicsemi.android:log:2.3.0')
@@ -76,11 +77,13 @@ include ':app'
include ':profile_bps'
include ':profile_cgms'
include ':profile_csc'
include ':profile_dfu'
include ':profile_gls'
include ':profile_hrs'
include ':profile_hts'
include ':profile_prx'
include ':profile_rscs'
include ':profile_uart'
include ':lib_service'
include ':lib_theme'
@@ -89,13 +92,3 @@ include ':lib_utils'
if (file('../Android-Common-Libraries').exists()) {
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'