From ce3bdd3d725e7c8c1a0b951e7aaf05579f3ab111 Mon Sep 17 00:00:00 2001 From: beetzung Date: Thu, 5 Mar 2026 21:38:07 +0100 Subject: [PATCH] feat(map): device panel contract, view model, arrow and close icons Made-with: Cursor --- .../airmq/features/map/MapScreenContract.kt | 10 ++- .../db3/airmq/features/map/MapViewModel.kt | 67 +++++++++++++++++-- .../main/res/drawable/ic_arrow_right_24.xml | 10 +++ app/src/main/res/drawable/ic_close_24.xml | 10 +++ 4 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 app/src/main/res/drawable/ic_arrow_right_24.xml create mode 100644 app/src/main/res/drawable/ic_close_24.xml 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 c178d46..706c24e 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 @@ -32,7 +32,12 @@ object MapScreenContract { val status: String, val selectedRange: TimeRange = TimeRange.DAY, val displayedDateRange: String = "", - val selectedSensor: DeviceSensorType = DeviceSensorType.TEMPERATURE + val selectedSensor: DeviceSensorType = DeviceSensorType.TEMPERATURE, + val supportedSensors: List = listOf( + DeviceSensorType.TEMPERATURE, + DeviceSensorType.DUST, + DeviceSensorType.RADIOACTIVITY + ) ) data class SearchPanelState( @@ -45,7 +50,8 @@ object MapScreenContract { val items: List = emptyList(), val selectedTopSensor: SensorType = SensorType.DUST, val searchPanelState: SearchPanelState? = null, - val devicePanelState: DevicePanelState? = null + val devicePanelState: DevicePanelState? = null, + val selectedMarkerId: String? = null ) sealed interface Action { 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 bdff7d2..8eedd5e 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 @@ -82,7 +82,8 @@ class MapViewModel @Inject constructor( val selectedItem = _uiState.value.items.firstOrNull { it.id == event.resultId } ?: return _uiState.value = _uiState.value.copy( searchPanelState = null, - devicePanelState = selectedItem.toDevicePanelState() + devicePanelState = selectedItem.toDevicePanelState(), + selectedMarkerId = event.resultId ) } @@ -99,13 +100,16 @@ class MapViewModel @Inject constructor( val selectedItem = _uiState.value.items.firstOrNull { it.id == event.itemId } ?: return _uiState.value = _uiState.value.copy( searchPanelState = null, - devicePanelState = selectedItem.toDevicePanelState() + devicePanelState = selectedItem.toDevicePanelState(), + selectedMarkerId = event.itemId ) } is Event.DevicePanelClosed -> { + val previousMarkerId = _uiState.value.devicePanelState?.id _uiState.value = _uiState.value.copy( - devicePanelState = null + devicePanelState = null, + selectedMarkerId = previousMarkerId ) } @@ -168,7 +172,9 @@ class MapViewModel @Inject constructor( domainItems = items val searchPanelState = _uiState.value.searchPanelState val selectedSensorType = _uiState.value.selectedTopSensor - val markers = items.toMarkers(selectedSensorType) + val markers = items.toMarkers(selectedSensorType).ifEmpty { + dummyMarkers(selectedSensorType) + } _uiState.value.copy( isLoading = false, items = markers, @@ -185,9 +191,10 @@ class MapViewModel @Inject constructor( ) ) val searchPanelState = _uiState.value.searchPanelState + val selectedSensorType = _uiState.value.selectedTopSensor _uiState.value.copy( isLoading = false, - items = emptyList(), + items = dummyMarkers(selectedSensorType), searchPanelState = searchPanelState?.copy(results = emptyList()) ) } @@ -220,11 +227,59 @@ class MapViewModel @Inject constructor( } private fun remapMarkers() { + val markers = domainItems.toMarkers(_uiState.value.selectedTopSensor) _uiState.value = _uiState.value.copy( - items = domainItems.toMarkers(_uiState.value.selectedTopSensor) + items = markers.ifEmpty { dummyMarkers(_uiState.value.selectedTopSensor) } ) } + private fun dummyMarkers(sensorType: SensorType): List = listOf( + MapMarker( + id = "dummy-1", + title = "AirMQ Demo #1", + city = "Minsk", + latitude = 53.9, + longitude = 27.56, + isOnline = true, + sensorType = sensorType, + value = 12.0, + isOwned = false + ), + MapMarker( + id = "dummy-2", + title = "AirMQ Demo #2", + city = "Minsk", + latitude = 53.85, + longitude = 27.65, + isOnline = true, + sensorType = sensorType, + value = 45.0, + isOwned = true + ), + MapMarker( + id = "dummy-3", + title = "AirMQ Demo #3", + city = "Minsk", + latitude = 53.75, + longitude = 27.45, + isOnline = false, + sensorType = sensorType, + value = 8.5, + isOwned = false + ), + MapMarker( + id = "dummy-4", + title = "AirMQ Demo #4", + city = null, + latitude = 53.82, + longitude = 27.92, + isOnline = true, + sensorType = sensorType, + value = null, + isOwned = false + ) + ) + private fun List.toMarkers(sensorType: SensorType): List { return mapNotNull { item -> val value = when (sensorType) { diff --git a/app/src/main/res/drawable/ic_arrow_right_24.xml b/app/src/main/res/drawable/ic_arrow_right_24.xml new file mode 100644 index 0000000..d334f67 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_right_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_close_24.xml b/app/src/main/res/drawable/ic_close_24.xml new file mode 100644 index 0000000..57511cc --- /dev/null +++ b/app/src/main/res/drawable/ic_close_24.xml @@ -0,0 +1,10 @@ + + +