Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
android:name="io.redlink.more.app.android.services.ObservationRecordingService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="dataSync" />
android:foregroundServiceType="dataSync|location|connectedDevice" />
<service
android:name="io.redlink.more.app.android.firebase.FCMService"
android:exported="false"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ import io.redlink.more.database.AppDatabase
import io.redlink.more.database.getDatabaseBuilder
import io.redlink.more.database.getRoomDatabase
import io.redlink.more.database.repository.MainRepositoryImpl
import io.redlink.more.logging.napierDebugBuild
import io.redlink.more.models.NotificationTextLocalization
import io.redlink.more.napierDebugBuild
import io.redlink.more.services.store.SharedPreferencesRepository
import io.redlink.more.viewModels.ViewManager

/**
* Main Application class of the project.
Expand All @@ -42,6 +43,9 @@ class MoreApplication : Application(), DefaultLifecycleObserver {
super<Application>.onCreate()
napierDebugBuild(FirebaseCrashlyticsAntilog())
napierDebugBuild()

firebaseAnalytics = FirebaseAnalytics.getInstance(this)

appContext = this
packagePath = this.packageName
appName = this.getString(R.string.app_name)
Expand All @@ -60,12 +64,14 @@ class MoreApplication : Application(), DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
Napier.i { "App is in the foreground..." }
ViewManager.appIsInForeground(true)
shared?.updateData(true)
}

override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
Napier.i { "App is in the background..." }
ViewManager.appIsInForeground(false)
shared?.updateData(false)
}

Expand Down Expand Up @@ -100,16 +106,23 @@ class MoreApplication : Application(), DefaultLifecycleObserver {
val database: AppDatabase = getRoomDatabase(getDatabaseBuilder(context))
val repositories = MainRepositoryImpl(database)
val dataManager = AndroidObservationDataManager(context, repositories)
shared = Shared(
val sharedPreferences = SharedPreferencesRepository(context)
val tempShared = Shared(
LocalPushNotificationService(context),
repositories,
SharedPreferencesRepository(context),
sharedPreferences,
dataManager,
androidBluetoothConnector,
AndroidObservationFactory(context, dataManager, repositories),
AndroidObservationFactory(
context,
dataManager,
repositories,
sharedPreferences,
),
AndroidDataRecorder()
)
shared?.let { shared ->
shared = tempShared
tempShared.let { shared ->
shared.deeplinkManager.setProtocol(Shared.PROTOCOL.toString(context))
shared.deeplinkManager.setHost(applicationId) // applicationId is needed instead of the shared HOST, as this is necessary for the NavController in Android
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import io.github.aakira.napier.Napier
import io.redlink.more.AlertController
import io.redlink.more.app.android.MoreApplication
import io.redlink.more.app.android.activities.main.MainActivity
import io.redlink.more.app.android.extensions.showNewActivityAndClearStack
import io.redlink.more.app.android.workers.ScheduleUpdateWorker
import io.redlink.more.models.AlertDialogModel
import io.redlink.more.dialog.AlertController
import io.redlink.more.dialog.AlertDialogModel
import io.redlink.more.registration.RegistrationService
import io.redlink.more.scopes.Scope
import io.redlink.more.services.notification.NotificationManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,23 @@
* (see https://www.apache.org/licenses/LICENSE-2.0 and
* https://commonsclause.com/).
*/
package io.redlink.more.app.android.activities.dashboard

import io.redlink.more.app.android.R
import io.redlink.more.app.android.extensions.stringResource
package io.redlink.more.app.android.activities

enum class Views(val tabPosition: Int, val tabText: String) {
SCHEDULE(tabPosition = 0, tabText = stringResource(R.string.more_main_tab_schedule)),
MODULES(tabPosition = 1, tabText = stringResource(R.string.more_main_tab_observations));
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect

@Composable
fun OnAppearDisappear(
onAppear: () -> Unit,
onDisappear: () -> Unit,
content: @Composable () -> Unit
) {
DisposableEffect(Unit) {
onAppear()
onDispose {
onDisappear()
}
}
content()
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import io.redlink.more.AlertController
import io.redlink.more.app.android.MoreApplication
import io.redlink.more.app.android.services.sensorsListener.BluetoothStateListener
import io.redlink.more.app.android.services.sensorsListener.GPSStateListener
import io.redlink.more.database.entities.BluetoothDeviceEntity
import io.redlink.more.models.AlertDialogModel
import io.redlink.more.dialog.AlertController
import io.redlink.more.dialog.AlertDialogModel
import io.redlink.more.scopes.Scope
import io.redlink.more.services.bluetooth.BluetoothStateManagement
import io.redlink.more.viewModels.ViewManager
Expand All @@ -29,7 +29,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class BluetoothViewModel : ViewModel() {
private val coreBluetoothViewModel = CoreBluetoothViewModel(
val coreViewModel = CoreBluetoothViewModel(
MoreApplication.shared!!.observationFactory,
MoreApplication.shared!!.bluetoothController
)
Expand Down Expand Up @@ -86,7 +86,7 @@ class BluetoothViewModel : ViewModel() {
}

viewModelScope.launch(Dispatchers.IO) {
coreBluetoothViewModel.devicesNeededToConnectTo.collect {
coreViewModel.devicesNeededToConnectTo.collect {
withContext(Dispatchers.Main) {
neededDevices.clear()
neededDevices.addAll(MoreApplication.shared!!.observationFactory.bleDevicesNeeded())
Expand All @@ -113,21 +113,21 @@ class BluetoothViewModel : ViewModel() {

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

fun viewDidDisappear() {
coreBluetoothViewModel.viewDidDisappear()
ViewManager.bleViewOpen(false)
coreViewModel.viewClosed()
}

fun connectToDevice(device: BluetoothDeviceEntity) {
Scope.launch {
coreBluetoothViewModel.connectToDevice(device)
coreViewModel.connectToDevice(device)
}
}

fun disconnectFromDevice(device: BluetoothDeviceEntity) {
coreBluetoothViewModel.disconnectFromDevice(device)
coreViewModel.disconnectFromDevice(device)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import io.redlink.more.app.android.activities.OnAppearDisappear
import io.redlink.more.app.android.activities.dashboard.schedule.ScheduleViewModel
import io.redlink.more.app.android.activities.dashboard.schedule.list.ScheduleListView
import io.redlink.more.app.android.activities.taskCompletion.TaskCompletionBarViewModel
Expand All @@ -32,25 +33,30 @@ fun CompletedSchedulesView(
navController: NavController,
taskCompletionBarViewModel: TaskCompletionBarViewModel
) {
Column(
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
) {
ScheduleListHeader(
viewModel = viewModel,
navController = navController,
taskCompletionBarViewModel = taskCompletionBarViewModel
)
Spacer(modifier = Modifier.height(10.dp))
Column {
ScheduleListView(
OnAppearDisappear(
{ viewModel.coreViewModel.viewDidAppear() },
{ viewModel.coreViewModel.viewDidDisappear() }) {

Column(
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
) {
ScheduleListHeader(
viewModel = viewModel,
navController = navController,
scheduleViewModel = viewModel,
showButton = false
taskCompletionBarViewModel = taskCompletionBarViewModel
)
Spacer(modifier = Modifier.height(10.dp))
Column {
ScheduleListView(
navController = navController,
scheduleViewModel = viewModel,
showButton = false
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import io.redlink.more.app.android.R
import io.redlink.more.app.android.activities.OnAppearDisappear
import io.redlink.more.app.android.activities.consent.composables.ConsentButtons
import io.redlink.more.app.android.extensions.getStringResource
import io.redlink.more.app.android.shared_composables.Accordion
Expand All @@ -42,51 +43,55 @@ fun ConsentView(registrationService: RegistrationService) {
val model = remember { ConsentViewModel(registrationService) }
val permissions by model.coreModel.permissions.collectAsStateWithLifecycle()
permissions?.let { permissionModel ->
LazyColumn(
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(0.9f)
) {
item {
Text(
text = permissionModel.studyTitle,
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
color = MoreColors.Primary,
modifier = Modifier.fillMaxWidth()
)
Spacer(Modifier.padding(8.dp))
AccordionReadMore(
title = getStringResource(id = R.string.participant_information),
description = permissionModel.studyParticipantInfo,
modifier = Modifier
.fillMaxWidth()
)
}
items(permissionModel.consentInfo) { consentInfo ->
Accordion(
title = if (permissionModel.consentInfo.indexOf(consentInfo) == 0)
permissionModel.studyTitle
else
consentInfo.title,
description = consentInfo.info,
hasCheck = true,
hasPreview = (permissionModel.consentInfo.indexOf(consentInfo) == 0)
)
}
item {
Spacer(modifier = Modifier.height(40.dp))
}
OnAppearDisappear(
{ model.coreModel.viewDidAppear() },
{ model.coreModel.viewDidDisappear() }) {
LazyColumn(
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(0.9f)
) {
item {
Text(
text = permissionModel.studyTitle,
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
color = MoreColors.Primary,
modifier = Modifier.fillMaxWidth()
)
Spacer(Modifier.padding(8.dp))
AccordionReadMore(
title = getStringResource(id = R.string.participant_information),
description = permissionModel.studyParticipantInfo,
modifier = Modifier
.fillMaxWidth()
)
}
items(permissionModel.consentInfo) { consentInfo ->
Accordion(
title = if (permissionModel.consentInfo.indexOf(consentInfo) == 0)
permissionModel.studyTitle
else
consentInfo.title,
description = consentInfo.info,
hasCheck = true,
hasPreview = (permissionModel.consentInfo.indexOf(consentInfo) == 0)
)
}
item {
Spacer(modifier = Modifier.height(40.dp))
}

item {
Box(
contentAlignment = Alignment.BottomCenter,
modifier = Modifier
.padding(bottom = 10.dp)
) {
ConsentButtons(model = model)
item {
Box(
contentAlignment = Alignment.BottomCenter,
modifier = Modifier
.padding(bottom = 10.dp)
) {
ConsentButtons(model = model)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ package io.redlink.more.app.android.activities.consent

import android.content.Context
import androidx.lifecycle.ViewModel
import io.redlink.more.AlertController
import dev.icerock.moko.resources.desc.Raw
import dev.icerock.moko.resources.desc.StringDesc
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.models.AlertDialogModel
import io.redlink.more.dialog.AlertController
import io.redlink.more.dialog.AlertDialogModel
import io.redlink.more.registration.RegistrationService
import io.redlink.more.viewModels.permission.CoreConsentViewModel

Expand All @@ -33,13 +35,17 @@ class ConsentViewModel(
}
}

fun openPermissionDeniedAlertDialog(context: Context) {
fun openPermissionDeniedAlertDialog(context: Context, missingPermissions: List<String> = emptyList()) {
var message = stringResource(R.string.required_permission_not_granted_message)
if (missingPermissions.isNotEmpty()) {
message += "\n\n" + stringResource(R.string.missing_permissions_label) + ": " + missingPermissions.joinToString(", ")
}
AlertController.openAlertDialog(
AlertDialogModel(
title = stringResource(R.string.required_permissions_not_granted_title),
message = stringResource(R.string.required_permission_not_granted_message),
confirmLabel = stringResource(R.string.proceed_to_settings_button),
cancelLabel = stringResource(R.string.proceed_without_granting_button),
title = StringDesc.Raw(stringResource(R.string.required_permissions_not_granted_title)),
message = StringDesc.Raw(message),
confirmLabel = StringDesc.Raw(stringResource(R.string.proceed_to_settings_button)),
cancelLabel = StringDesc.Raw(stringResource(R.string.proceed_without_granting_button)),
onConfirm = {
MoreApplication.openSettings.value = true
},
Expand All @@ -52,10 +58,10 @@ class ConsentViewModel(
fun openNotificationPermissionDeniedAlertDialog(context: Context) {
AlertController.openAlertDialog(
AlertDialogModel(
title = stringResource(R.string.notification_permission_not_granted_title),
message = stringResource(R.string.notification_permission_not_granted_message),
confirmLabel = stringResource(R.string.proceed_to_settings_button),
cancelLabel = stringResource(R.string.proceed_without_granting_button),
title = StringDesc.Raw(stringResource(R.string.notification_permission_not_granted_title)),
message = StringDesc.Raw(stringResource(R.string.notification_permission_not_granted_message)),
confirmLabel = StringDesc.Raw(stringResource(R.string.proceed_to_settings_button)),
cancelLabel = StringDesc.Raw(stringResource(R.string.proceed_without_granting_button)),
onConfirm = {
MoreApplication.openSettings.value = true
},
Expand Down
Loading
Loading