From fee67c35af00b42cd43442b41ce68a78c9cb4fa4 Mon Sep 17 00:00:00 2001 From: beetzung Date: Mon, 16 Mar 2026 16:45:48 +0100 Subject: [PATCH] feat: add AQI/RAD help dialog on map screen --- .../org/db3/airmq/features/map/MapScreen.kt | 12 ++- .../airmq/features/map/MapScreenContract.kt | 5 +- .../db3/airmq/features/map/MapUiComponents.kt | 81 ++++++++++++++++++ .../db3/airmq/features/map/MapViewModel.kt | 8 ++ app/src/main/res/drawable/aqi_table.png | Bin 0 -> 21716 bytes 5 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 app/src/main/res/drawable/aqi_table.png diff --git a/app/src/main/kotlin/org/db3/airmq/features/map/MapScreen.kt b/app/src/main/kotlin/org/db3/airmq/features/map/MapScreen.kt index 51bec86..221bfa3 100644 --- a/app/src/main/kotlin/org/db3/airmq/features/map/MapScreen.kt +++ b/app/src/main/kotlin/org/db3/airmq/features/map/MapScreen.kt @@ -119,19 +119,17 @@ private fun MapScreenContent( MapTopControls( selectedSensor = uiState.selectedTopSensor, onSensorSelected = { onEvent(Event.TopSensorSelected(it)) }, - onHelpClick = { - Toast.makeText( - context, - context.getString(R.string.text_what_does_it_mean_title), - Toast.LENGTH_SHORT - ).show() - }, + onHelpClick = { onEvent(Event.HelpClicked) }, modifier = Modifier .align(Alignment.TopEnd) .statusBarsPadding() .padding(top = 20.dp, end = 16.dp) ) + if (uiState.showHelpDialog) { + WhatDoesThisMeanDialog(onDismiss = { onEvent(Event.HelpDialogDismissed) }) + } + if (uiState.searchPanelState == null && uiState.devicePanelState == null) { MapFloatingActions( onSearchClick = { onEvent(Event.SearchButtonClicked) }, diff --git a/app/src/main/kotlin/org/db3/airmq/features/map/MapScreenContract.kt b/app/src/main/kotlin/org/db3/airmq/features/map/MapScreenContract.kt index 706c24e..b3f5864 100644 --- a/app/src/main/kotlin/org/db3/airmq/features/map/MapScreenContract.kt +++ b/app/src/main/kotlin/org/db3/airmq/features/map/MapScreenContract.kt @@ -51,7 +51,8 @@ object MapScreenContract { val selectedTopSensor: SensorType = SensorType.DUST, val searchPanelState: SearchPanelState? = null, val devicePanelState: DevicePanelState? = null, - val selectedMarkerId: String? = null + val selectedMarkerId: String? = null, + val showHelpDialog: Boolean = false ) sealed interface Action { @@ -67,6 +68,8 @@ object MapScreenContract { data class SearchResultClicked(val resultId: String) : Event data object MyLocationClicked : Event data class TopSensorSelected(val sensor: SensorType) : Event + data object HelpClicked : Event + data object HelpDialogDismissed : Event data class MarkerClicked(val itemId: String) : Event data object DevicePanelClosed : Event data object DeviceOpenClicked : Event diff --git a/app/src/main/kotlin/org/db3/airmq/features/map/MapUiComponents.kt b/app/src/main/kotlin/org/db3/airmq/features/map/MapUiComponents.kt index 48132b8..9f59d96 100644 --- a/app/src/main/kotlin/org/db3/airmq/features/map/MapUiComponents.kt +++ b/app/src/main/kotlin/org/db3/airmq/features/map/MapUiComponents.kt @@ -1,5 +1,6 @@ package org.db3.airmq.features.map +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -12,10 +13,13 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults @@ -27,6 +31,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Surface import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween import androidx.compose.animation.expandVertically @@ -38,6 +43,10 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Brush @@ -220,6 +229,78 @@ fun MapTopControls( } } +@Composable +fun WhatDoesThisMeanDialog( + onDismiss: () -> Unit +) { + Dialog(onDismissRequest = onDismiss) { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 32.dp, vertical = 128.dp), + shape = RoundedCornerShape(24.dp), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface) + ) { + Column( + modifier = Modifier.padding(24.dp) + ) { + Text( + text = stringResource(id = R.string.text_what_does_it_mean_title), + style = MaterialTheme.typography.titleMedium, + fontSize = 16.sp, + fontWeight = FontWeight.Medium, + modifier = Modifier.padding(bottom = 22.dp) + ) + Column( + modifier = Modifier + .heightIn(max = 400.dp) + .verticalScroll(rememberScrollState()) + .padding(horizontal = 0.dp) + ) { + Text( + text = stringResource(id = R.string.text_aqi_title), + style = MaterialTheme.typography.bodyLarge, + fontSize = 16.sp, + fontWeight = FontWeight.Medium + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = stringResource(id = R.string.text_aqi), + style = MaterialTheme.typography.bodyMedium + ) + Spacer(modifier = Modifier.height(8.dp)) + Image( + painter = painterResource(id = R.drawable.aqi_table), + contentDescription = null, + contentScale = ContentScale.Fit, + modifier = Modifier + .width(300.dp) + .height(150.dp) + ) + Spacer(modifier = Modifier.height(20.dp)) + Text( + text = stringResource(id = R.string.text_rad_title), + style = MaterialTheme.typography.bodyLarge, + fontSize = 16.sp, + fontWeight = FontWeight.Medium + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = stringResource(id = R.string.text_rad), + style = MaterialTheme.typography.bodyMedium + ) + } + TextButton( + onClick = onDismiss, + modifier = Modifier.align(Alignment.End) + ) { + Text(stringResource(id = R.string.button_ok)) + } + } + } + } +} + @Composable private fun SensorTypeItem( iconRes: Int, diff --git a/app/src/main/kotlin/org/db3/airmq/features/map/MapViewModel.kt b/app/src/main/kotlin/org/db3/airmq/features/map/MapViewModel.kt index 8eedd5e..133e727 100644 --- a/app/src/main/kotlin/org/db3/airmq/features/map/MapViewModel.kt +++ b/app/src/main/kotlin/org/db3/airmq/features/map/MapViewModel.kt @@ -96,6 +96,14 @@ class MapViewModel @Inject constructor( remapMarkers() } + Event.HelpClicked -> { + _uiState.value = _uiState.value.copy(showHelpDialog = true) + } + + Event.HelpDialogDismissed -> { + _uiState.value = _uiState.value.copy(showHelpDialog = false) + } + is Event.MarkerClicked -> { val selectedItem = _uiState.value.items.firstOrNull { it.id == event.itemId } ?: return _uiState.value = _uiState.value.copy( diff --git a/app/src/main/res/drawable/aqi_table.png b/app/src/main/res/drawable/aqi_table.png new file mode 100644 index 0000000000000000000000000000000000000000..00efbea65a274419ae3b655d75697995a93183fe GIT binary patch literal 21716 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 literal 0 HcmV?d00001