From 9ba17c7d72847c2509a41f57245776d1dbc12eb5 Mon Sep 17 00:00:00 2001 From: KremeCN <3265494849@qq.com> Date: Wed, 26 Aug 2026 19:32:12 +0800 Subject: [PATCH] feat: render partial sensor readings --- .../TemperatureHumidityScreen.kt | 34 +++++++++---------- .../TemperatureHumidityUiState.kt | 8 ++--- .../TemperatureHumidityViewModel.kt | 6 ++-- .../TemperatureHumidityViewModelTest.kt | 16 +++++++-- .../flagship/abox/manager/domain/Models.kt | 4 +-- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityScreen.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityScreen.kt index 3cf5571..1c2f13b 100644 --- a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityScreen.kt +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityScreen.kt @@ -40,6 +40,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.flagship.abox.manager.R import com.flagship.abox.manager.designsystem.ABoxButton import com.flagship.abox.manager.designsystem.ABoxLoadingIndicator +import com.flagship.abox.manager.designsystem.icon.ABoxIcon +import com.flagship.abox.manager.designsystem.icon.ABoxIconKey import com.flagship.abox.manager.domain.DeviceName import java.text.SimpleDateFormat import java.util.Date @@ -159,17 +161,17 @@ fun TemperatureHumidityScreen( ) { TelemetryMetricCard( title = stringResource(R.string.th_temperature_label), - value = state.temperature ?: "--", + value = state.temperature, unit = stringResource(R.string.th_unit_celsius), - icon = "🌡️", + icon = ABoxIconKey.TEMPERATURE, modifier = Modifier.weight(1f), ) TelemetryMetricCard( title = stringResource(R.string.th_humidity_label), - value = state.humidity ?: "--", + value = state.humidity, unit = stringResource(R.string.th_unit_percent), - icon = "💧", + icon = ABoxIconKey.HUMIDITY, modifier = Modifier.weight(1f), ) } @@ -279,11 +281,12 @@ fun TemperatureHumidityScreen( @Composable private fun TelemetryMetricCard( title: String, - value: String, + value: String?, unit: String, - icon: String, + icon: ABoxIconKey, modifier: Modifier = Modifier, ) { + if (value == null) return Card( modifier = modifier, colors = CardDefaults.cardColors( @@ -298,10 +301,7 @@ private fun TelemetryMetricCard( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { - Text( - text = icon, - style = MaterialTheme.typography.headlineMedium, - ) + ABoxIcon(icon, contentDescription = title, modifier = Modifier.size(28.dp)) Spacer(modifier = Modifier.height(8.dp)) @@ -323,14 +323,12 @@ private fun TelemetryMetricCard( fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.primary, ) - if (value != "--") { - Text( - text = " $unit", - style = MaterialTheme.typography.titleMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.padding(bottom = 4.dp), - ) - } + Text( + text = " $unit", + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.padding(bottom = 4.dp), + ) } } } diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityUiState.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityUiState.kt index 678a497..39e0cf8 100644 --- a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityUiState.kt +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityUiState.kt @@ -16,11 +16,11 @@ data class TemperatureHumidityUiState( val errorMessage: UiText? = null, val lastUpdatedTimeMillis: Long? = null, ) { - val formattedTemperature: String - get() = if (temperature.isNullOrBlank()) "--" else "$temperature °C" + val formattedTemperature: String? + get() = temperature?.takeIf { it.isNotBlank() }?.let { "$it °C" } - val formattedHumidity: String - get() = if (humidity.isNullOrBlank()) "--" else "$humidity %" + val formattedHumidity: String? + get() = humidity?.takeIf { it.isNotBlank() }?.let { "$it %" } val hasValidData: Boolean get() = !temperature.isNullOrBlank() || !humidity.isNullOrBlank() diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityViewModel.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityViewModel.kt index 916fc80..bc5c8e8 100644 --- a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityViewModel.kt +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityViewModel.kt @@ -101,11 +101,11 @@ class TemperatureHumidityViewModel @Inject constructor( when (val result = thGateway.getReading(profileId, deviceName)) { is DomainResult.Success -> { val reading = result.value - val isBlankData = reading.temperature.isBlank() && reading.humidity.isBlank() + val isBlankData = reading.temperature.isNullOrBlank() && reading.humidity.isNullOrBlank() _state.update { it.copy( - temperature = reading.temperature.takeIf { t -> t.isNotBlank() }, - humidity = reading.humidity.takeIf { h -> h.isNotBlank() }, + temperature = reading.temperature?.takeIf { t -> t.isNotBlank() }, + humidity = reading.humidity?.takeIf { h -> h.isNotBlank() }, isLoading = false, isRefreshing = false, isOffline = false, diff --git a/android/app/src/test/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityViewModelTest.kt b/android/app/src/test/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityViewModelTest.kt index b5c2512..485df55 100644 --- a/android/app/src/test/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityViewModelTest.kt +++ b/android/app/src/test/kotlin/com/flagship/abox/manager/ui/temperaturehumidity/TemperatureHumidityViewModelTest.kt @@ -129,8 +129,8 @@ class TemperatureHumidityViewModelTest { assertTrue(state.hasNoData) assertNull(state.temperature) assertNull(state.humidity) - assertEquals("--", state.formattedTemperature) - assertEquals("--", state.formattedHumidity) + assertNull(state.formattedTemperature) + assertNull(state.formattedHumidity) assertFalse(state.hasValidData) } @@ -190,4 +190,16 @@ class TemperatureHumidityViewModelTest { viewModel.onEvent(TemperatureHumidityUiEvent.ClearError) assertNull(viewModel.state.value.errorMessage) } + + @Test + fun partialReadingKeepsAvailableMetric() = runTest { + fakeGateway.setReading( + TemperatureHumidityReading(profileId, deviceName, temperature = "26.5", humidity = null), + ) + val viewModel = TemperatureHumidityViewModel(fakeGateway, SavedStateHandle()) + viewModel.onEvent(TemperatureHumidityUiEvent.Initialize(profileId, deviceName)) + + assertEquals("26.5", viewModel.state.value.temperature) + assertNull(viewModel.state.value.humidity) + } } diff --git a/domain/src/main/kotlin/com/flagship/abox/manager/domain/Models.kt b/domain/src/main/kotlin/com/flagship/abox/manager/domain/Models.kt index b1e1cc4..b3051e6 100644 --- a/domain/src/main/kotlin/com/flagship/abox/manager/domain/Models.kt +++ b/domain/src/main/kotlin/com/flagship/abox/manager/domain/Models.kt @@ -83,8 +83,8 @@ data class SocketStatus( data class TemperatureHumidityReading( val profileId: ProviderProfileId, val deviceName: DeviceName, - val temperature: String, - val humidity: String, + val temperature: String?, + val humidity: String?, ) data class InfraredCode(