Skip to content

Commit

Permalink
#200: Rebuilt the BLE Core, Controller, implemented a few warning dis…
Browse files Browse the repository at this point in the history
…plays and extended the Coroutine System to differentiate between app critical coroutines and study critical ones
  • Loading branch information
janoliver20 committed Apr 30, 2024
1 parent 405f290 commit f5f435a
Show file tree
Hide file tree
Showing 66 changed files with 824 additions and 672 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import io.redlink.more.app.android.extensions.applicationId
import io.redlink.more.app.android.extensions.showNewActivityAndClearStack
import io.redlink.more.app.android.extensions.stringResource
import io.redlink.more.app.android.workers.ScheduleUpdateWorker
import io.redlink.more.more_app_mutliplatform.AlertController
import io.redlink.more.more_app_mutliplatform.models.AlertDialogModel
import io.redlink.more.more_app_mutliplatform.services.network.RegistrationService
import io.redlink.more.more_app_mutliplatform.services.network.openapi.model.Study
Expand Down Expand Up @@ -59,7 +60,7 @@ class ContentViewModel : ViewModel(), LoginViewModelListener, ConsentViewModelLi

init {
viewModelScope.launch(Dispatchers.IO) {
MoreApplication.shared!!.mainContentCoreViewModel.alertDialogModel.collect {
AlertController.alertDialogModel.collect {
withContext(Dispatchers.Main) {
alertDialogOpen.value = it
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import io.redlink.more.app.android.MoreApplication
import io.redlink.more.more_app_mutliplatform.AlertController
import io.redlink.more.more_app_mutliplatform.models.AlertDialogModel
import io.redlink.more.more_app_mutliplatform.services.bluetooth.BluetoothDevice
import io.redlink.more.more_app_mutliplatform.services.bluetooth.BluetoothDeviceManager
import io.redlink.more.more_app_mutliplatform.services.bluetooth.BluetoothState
import io.redlink.more.more_app_mutliplatform.viewModels.ViewManager
import io.redlink.more.more_app_mutliplatform.viewModels.startupConnection.CoreBluetoothViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand All @@ -27,7 +29,7 @@ import kotlinx.coroutines.withContext
class BluetoothViewModel : ViewModel() {
private val coreBluetoothViewModel = CoreBluetoothViewModel(
MoreApplication.shared!!.observationFactory,
MoreApplication.shared!!.coreBluetooth
MoreApplication.shared!!.bluetoothController
)
val discoveredDevices = mutableStateListOf<BluetoothDevice>()
val connectedDevices = mutableStateListOf<BluetoothDevice>()
Expand All @@ -42,7 +44,7 @@ class BluetoothViewModel : ViewModel() {

init {
viewModelScope.launch(Dispatchers.IO) {
MoreApplication.shared!!.mainContentCoreViewModel.alertDialogModel.collect {
AlertController.alertDialogModel.collect {
withContext(Dispatchers.Main) {
alertDialogOpen.value = it
}
Expand Down Expand Up @@ -90,9 +92,11 @@ class BluetoothViewModel : ViewModel() {

fun viewDidAppear() {
coreBluetoothViewModel.viewDidAppear()
ViewManager.bleViewOpen(true)
}

fun viewDidDisappear() {
ViewManager.bleViewOpen(false)
coreBluetoothViewModel.viewDidDisappear()
connectingDevices.clear()
connectedDevices.clear()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import io.redlink.more.app.android.MoreApplication
import io.redlink.more.app.android.R
import io.redlink.more.app.android.extensions.getSecureID
import io.redlink.more.app.android.extensions.stringResource
import io.redlink.more.more_app_mutliplatform.AlertController
import io.redlink.more.more_app_mutliplatform.models.AlertDialogModel
import io.redlink.more.more_app_mutliplatform.models.PermissionModel
import io.redlink.more.more_app_mutliplatform.services.extensions.toMD5
Expand All @@ -36,11 +37,19 @@ class ConsentViewModel(
registrationService: RegistrationService,
private val consentViewModelListener: ConsentViewModelListener
) : ViewModel() {
private val coreModel = CorePermissionViewModel(registrationService, stringResource(R.string.consent_information))
private val coreModel =
CorePermissionViewModel(registrationService, stringResource(R.string.consent_information))
private var consentInfo: String? = null

val permissionModel =
mutableStateOf(PermissionModel("Title", "Participation Info", "Study Consent Info", emptyList()))
mutableStateOf(
PermissionModel(
"Title",
"Participation Info",
"Study Consent Info",
emptyList()
)
)
val loading = mutableStateOf(false)
val error = mutableStateOf<String?>(null)
val permissions = mutableSetOf<String>()
Expand Down Expand Up @@ -83,34 +92,34 @@ class ConsentViewModel(
}

fun openPermissionDeniedAlertDialog(context: Context) {
MoreApplication.shared!!.mainContentCoreViewModel.openAlertDialog(AlertDialogModel(
AlertController.openAlertDialog(AlertDialogModel(
title = stringResource(R.string.required_permissions_not_granted_title),
message = stringResource(R.string.required_permission_not_granted_message),
positiveTitle = stringResource(R.string.proceed_to_settings_button),
negativeTitle = stringResource(R.string.proceed_without_granting_button),
onPositive = {
MoreApplication.openSettings.value = true
MoreApplication.shared!!.mainContentCoreViewModel.closeAlertDialog()
AlertController.closeAlertDialog()
},
onNegative = {
acceptConsent(context)
MoreApplication.shared!!.mainContentCoreViewModel.closeAlertDialog()
AlertController.closeAlertDialog()
}
))
}

fun openNotificationPermissionDeniedAlertDialog() {
MoreApplication.shared!!.mainContentCoreViewModel.openAlertDialog(AlertDialogModel(
AlertController.openAlertDialog(AlertDialogModel(
title = stringResource(R.string.notification_permission_not_granted_title),
message = stringResource(R.string.notification_permission_not_granted_message),
positiveTitle = stringResource(R.string.proceed_to_settings_button),
negativeTitle = stringResource(R.string.proceed_without_granting_button),
onPositive = {
MoreApplication.openSettings.value = true
MoreApplication.shared!!.mainContentCoreViewModel.closeAlertDialog()
AlertController.closeAlertDialog()
},
onNegative = {
MoreApplication.shared!!.mainContentCoreViewModel.closeAlertDialog()
AlertController.closeAlertDialog()
}
))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,43 @@ import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import io.redlink.more.app.android.MoreApplication
import io.redlink.more.app.android.activities.dashboard.filter.DashboardFilterViewModel
import io.redlink.more.app.android.extensions.jvmLocalDate
import io.redlink.more.app.android.observations.HR.PolarHeartRateObservation
import io.redlink.more.more_app_mutliplatform.models.ScheduleListType
import io.redlink.more.more_app_mutliplatform.models.ScheduleModel
import io.redlink.more.more_app_mutliplatform.observations.DataRecorder
import io.redlink.more.more_app_mutliplatform.viewModels.dashboard.CoreDashboardFilterViewModel
import io.redlink.more.more_app_mutliplatform.viewModels.schedules.CoreScheduleViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.time.LocalDate

class ScheduleViewModel(
coreFilterModel: CoreDashboardFilterViewModel,
dataRecorder: DataRecorder,
val scheduleListType: ScheduleListType
) : ViewModel() {
private val coreDashboardFilterViewModel = CoreDashboardFilterViewModel()

private val coreViewModel = CoreScheduleViewModel(
dataRecorder,
coreFilterModel = coreFilterModel,
MoreApplication.shared!!.dataRecorder,
coreFilterModel = coreDashboardFilterViewModel,
scheduleListType = scheduleListType
)

val polarHrReady: MutableState<Boolean> = mutableStateOf(false)

val schedulesByDate = mutableStateMapOf<LocalDate, List<ScheduleModel>>()
val observationErrors = mutableStateMapOf<String, Set<String>>()

val filterModel = DashboardFilterViewModel(coreFilterModel)
val filterModel = DashboardFilterViewModel(coreDashboardFilterViewModel)

init {
viewModelScope.launch {
private val jobs = mutableListOf<Job>()

fun viewDidAppear() {
coreViewModel.viewDidAppear()
jobs.add(viewModelScope.launch {
coreViewModel.scheduleListState.collect { (added, removed, updated) ->
val idsToRemove = removed + updated.map { it.scheduleId }.toSet()
schedulesByDate.forEach { (date, schedules) ->
Expand All @@ -61,34 +65,28 @@ class ScheduleViewModel(
).sortedBy { it.start }
}
}
}
viewModelScope.launch(Dispatchers.IO) {
})
jobs.add(viewModelScope.launch(Dispatchers.IO) {
PolarHeartRateObservation.hrReady.collect {
withContext(Dispatchers.Main) {
polarHrReady.value = it
// val polarSchedules = schedulesByDate.values.flatten().filter { it.observationType == "polar-verity-observation" }
// if (!it) {
// polarSchedules.filter { it.scheduleState == ScheduleState.RUNNING }
// .forEach {
// pauseObservation(it.scheduleId)
// }
// } else {
// polarSchedules.filter { it.scheduleState == ScheduleState.PAUSED }
// .forEach {
// startObservation(it.scheduleId)
// }
// }
}
}
}
}

fun viewDidAppear() {
coreViewModel.viewDidAppear()
})
jobs.add(viewModelScope.launch(Dispatchers.IO) {
MoreApplication.shared!!.observationFactory.observationErrors.collect {
withContext(Dispatchers.Main) {
observationErrors.clear()
observationErrors.putAll(it)
}
}
})
}

fun viewDidDisappear() {
coreViewModel.viewDidDisappear()
jobs.forEach { it.cancel() }
jobs.clear()
}

fun startObservation(scheduleId: String) {
Expand All @@ -103,6 +101,7 @@ class ScheduleViewModel(
coreViewModel.stop(scheduleId)
}


private fun mergeSchedules(
first: Set<ScheduleModel>,
second: Set<ScheduleModel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Icon
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.KeyboardArrowRight
import androidx.compose.material.icons.filled.Warning
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
Expand All @@ -47,6 +49,8 @@ fun ScheduleListItem(
viewModel: ScheduleViewModel,
showButton: Boolean
) {
val observationErrors =
remember { viewModel.observationErrors[scheduleModel.observationType] ?: emptySet() }
Column(
verticalArrangement = Arrangement.SpaceEvenly,
modifier = Modifier
Expand All @@ -69,6 +73,9 @@ fun ScheduleListItem(
.width(15.dp)
)
}
if (observationErrors.isEmpty()) {
Icon(Icons.Default.Warning, contentDescription = null, tint = MoreColors.Primary)
}
}
Row(
horizontalArrangement = Arrangement.SpaceBetween,
Expand Down Expand Up @@ -99,6 +106,7 @@ fun ScheduleListItem(
)
}
}

"lime-survey-observation" -> {
SmallTextButton(
text = getStringResource(id = R.string.more_limesurvey_start),
Expand All @@ -107,6 +115,7 @@ fun ScheduleListItem(
navController.navigate(NavigationScreen.LIMESURVEY.navigationRoute("scheduleId" to scheduleModel.scheduleId))
}
}

else -> {
SmallTextButton(
text = if (scheduleModel.scheduleState == ScheduleState.RUNNING) getStringResource(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ class MainActivity : ComponentActivity() {

LaunchedEffect(Unit) {
navHostController.addOnDestinationChangedListener(destinationChangeListener)
viewModel.viewDidAppear()
}
if (viewModel.studyIsUpdating.value) {
StudyUpdateView()
Expand Down
Loading

0 comments on commit f5f435a

Please sign in to comment.