Skip to content

Commit

Permalink
Load sensor setting dialog entries async (#4579)
Browse files Browse the repository at this point in the history
- When tapping a sensor setting, load setting dialog entries asynchronously to prevent the app getting an ANR. Show a nice loading dialog as well after a second.
  • Loading branch information
jpelgrom authored Sep 8, 2024
1 parent 90139ab commit 4865b10
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import io.homeassistant.companion.android.sensors.SensorReceiver
import javax.inject.Inject
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down Expand Up @@ -75,6 +76,8 @@ class SensorDetailViewModel @Inject constructor(
)
data class SettingDialogState(
val setting: SensorSetting,
/** Indicates if this is still loading entries in the background */
val loading: Boolean,
/** List of entity ID to entity pairs */
val entries: List<Pair<String, String>>,
/** List of selected entity ID */
Expand Down Expand Up @@ -225,14 +228,27 @@ class SensorDetailViewModel @Inject constructor(
fun setServersExpanded(expand: Boolean) = viewModelScope.launch { _serversDoExpand.emit(expand) }

/**
* Builds a SettingDialogState based on the given Sensor Setting.
* Builds a SettingDialogState based on the given Sensor Setting. Depending on the
* device and/or connection, this may take some time.
* Should trigger a dialog open in view.
*/
fun onSettingWithDialogPressed(setting: SensorSetting) {
fun onSettingWithDialogPressed(setting: SensorSetting) = viewModelScope.launch {
val dialogLoadingJob = launch {
// In case getting entries takes too long, display a temporary loading dialog
delay(1000L)
sensorSettingsDialog = SettingDialogState(
setting = setting,
loading = true,
entries = listOf(),
entriesSelected = listOf()
)
}

val listKeys = getSettingKeys(setting)
val listEntries = getSettingEntries(setting, null)
val state = SettingDialogState(
setting = setting,
loading = false,
entries = when {
setting.valueType == SensorSettingType.LIST ||
setting.valueType == SensorSettingType.LIST_APPS ||
Expand All @@ -256,6 +272,7 @@ class SensorDetailViewModel @Inject constructor(
emptyList()
}
)
dialogLoadingJob.cancel()
sensorSettingsDialog = state
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.Card
import androidx.compose.material.Checkbox
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.ContentAlpha
import androidx.compose.material.Divider
import androidx.compose.material.LocalContentAlpha
Expand All @@ -51,7 +52,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.ColorFilter
Expand Down Expand Up @@ -484,7 +484,6 @@ fun SensorDetailRow(
}
}

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun SensorDetailSettingDialog(
viewModel: SensorDetailViewModel,
Expand All @@ -494,14 +493,23 @@ fun SensorDetailSettingDialog(
) {
val keyboardController = LocalSoftwareKeyboardController.current
val listSettingDialog = state.setting.valueType.listType
val inputValue = remember { mutableStateOf(state.setting.value) }
val checkedValue = remember { mutableStateListOf<String>().also { it.addAll(state.entriesSelected) } }
val inputValue = remember(state.loading) { mutableStateOf(state.setting.value) }
val checkedValue = remember(state.loading) { mutableStateListOf<String>().also { it.addAll(state.entriesSelected) } }

MdcAlertDialog(
onDismissRequest = onDismiss,
title = { Text(viewModel.getSettingTranslatedTitle(state.setting.name)) },
content = {
if (listSettingDialog) {
if (state.loading) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.Center
) {
CircularProgressIndicator()
}
} else if (listSettingDialog) {
LazyColumn {
items(state.entries, key = { (id) -> id }) { (id, entry) ->
SensorDetailSettingRow(
Expand Down Expand Up @@ -540,7 +548,9 @@ fun SensorDetailSettingDialog(
}
},
onCancel = onDismiss,
onSave = if (state.setting.valueType != SensorSettingType.LIST) {
onSave = if (state.loading) {
null
} else if (state.setting.valueType != SensorSettingType.LIST) {
{
if (listSettingDialog) {
inputValue.value = checkedValue.joinToString().replace("[", "").replace("]", "")
Expand Down

0 comments on commit 4865b10

Please sign in to comment.