diff --git a/app/src/main/kotlin/org/db3/airmq/features/dashboard/DashboardScreen.kt b/app/src/main/kotlin/org/db3/airmq/features/dashboard/DashboardScreen.kt index e549b1b..16af1cd 100644 --- a/app/src/main/kotlin/org/db3/airmq/features/dashboard/DashboardScreen.kt +++ b/app/src/main/kotlin/org/db3/airmq/features/dashboard/DashboardScreen.kt @@ -7,27 +7,28 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel import org.db3.airmq.R -import org.db3.airmq.features.common.MockScreenScaffold -import org.db3.airmq.features.common.metric.MetricGaugeRow -import org.db3.airmq.features.common.metric.SensorType -import org.db3.airmq.features.common.ScreenAction import org.db3.airmq.features.common.chart.AirMQChart -import org.db3.airmq.features.common.chart.ChartConfig -import org.db3.airmq.features.common.chart.ChartDataset -import org.db3.airmq.features.common.chart.generateSineWaveData -import org.db3.airmq.ui.theme.ChartBackground -import org.db3.airmq.ui.theme.ChartFill +import org.db3.airmq.features.common.metric.MetricGaugePager +import org.db3.airmq.features.common.metric.SensorType +import org.db3.airmq.ui.theme.AirMQTheme import org.db3.airmq.ui.theme.LegacyNavGradientEnd import org.db3.airmq.ui.theme.LegacyNavGradientStart @@ -38,57 +39,105 @@ fun DashboardScreen( onOpenCity: () -> Unit, onOpenDevice: () -> Unit, onOpenNews: () -> Unit, - onOpenWidgetConstructor: () -> Unit + onOpenWidgetConstructor: () -> Unit, + viewModel: DashboardViewModel = hiltViewModel() ) { - MockScreenScaffold( - title = stringResource(id = R.string.title_dashboard), - subtitle = stringResource(id = R.string.dashboard_subtitle), - content = { - var selectedSensor by remember { mutableStateOf(SensorType.DUST) } - Column( - modifier = Modifier - .fillMaxWidth() - .background( - Brush.verticalGradient( - colors = listOf(LegacyNavGradientStart, LegacyNavGradientEnd) - ) - ) - ) { - MetricGaugeRow( - selectedSensor = selectedSensor, - values = mapOf( - SensorType.DUST to 6f, - SensorType.RADIOACTIVITY to 0f, - SensorType.TEMPERATURE to 3f - ), - onGaugeSelected = { selectedSensor = it }, - modifier = Modifier.padding(vertical = 8.dp) - ) - Box( - modifier = Modifier - .fillMaxWidth() - .height(144.dp) - ) { - AirMQChart( - data = ChartDataset.Single(generateSineWaveData()), - config = ChartConfig( - lineColor = Color.White, - fillColor = ChartFill, - backgroundColor = ChartBackground, - labelColor = Color.White, - leftTimeLabel = stringResource(R.string.text_yesterday), - rightTimeLabel = stringResource(R.string.text_now), - unit = "°C" - ), - sensorType = "sensor_temperature", - modifier = Modifier.fillMaxSize() - ) - } - } - }, - actions = listOf( - ScreenAction(stringResource(id = R.string.dashboard_open_news), onOpenNews), - ScreenAction(stringResource(id = R.string.manage_open_widget_constructor), onOpenWidgetConstructor) - ) + val state by viewModel.uiState.collectAsState() + DashboardContent( + state = state, + onEvent = viewModel::onEvent ) } + +@Composable +internal fun DashboardContent( + state: DashboardScreenContract.State, + onEvent: (DashboardScreenContract.Event) -> Unit +) { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .background( + Brush.verticalGradient( + colors = listOf(LegacyNavGradientStart, LegacyNavGradientEnd) + ) + ) + .statusBarsPadding() + ) { + CitySelector(city = state.city, modifier = Modifier.padding(top = 12.dp)) + MetricGaugePager( + selectedSensor = state.selectedSensor, + values = state.gaugeValues, + currentPage = state.currentPage, + onGaugeSelected = { onEvent(DashboardScreenContract.Event.GaugeSelected(it)) }, + onPageChanged = { onEvent(DashboardScreenContract.Event.PageChanged(it)) }, + modifier = Modifier.fillMaxWidth() + ) + Box( + modifier = Modifier + .fillMaxWidth() + .height(144.dp) + ) { + AirMQChart( + data = state.chartData, + config = state.chartConfig.copy( + leftTimeLabel = stringResource(R.string.text_yesterday), + rightTimeLabel = stringResource(R.string.text_now) + ), + sensorType = state.selectedSensor.legacyKey, + modifier = Modifier.fillMaxSize() + ) + } + } + } +} + +@Composable +private fun CitySelector( + city: String, + modifier: Modifier = Modifier +) { + Box( + modifier = modifier + .fillMaxWidth() + .height(44.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = city, + color = Color.White, + fontSize = 22.sp, + fontWeight = FontWeight.Medium + ) + } +} + +@Preview(showBackground = true, name = "Dashboard – dust selected") +@Composable +private fun PreviewDashboardDust() { + AirMQTheme { + DashboardContent( + state = DashboardScreenContract.previewState(selectedSensor = SensorType.DUST), + onEvent = {} + ) + } +} + +@Preview(showBackground = true, name = "Dashboard – page 2 humidity") +@Composable +private fun PreviewDashboardPage2() { + AirMQTheme { + DashboardContent( + state = DashboardScreenContract.previewState( + selectedSensor = SensorType.HUMIDITY, + currentPage = 1 + ), + onEvent = {} + ) + } +} 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 323010e..76be2e4 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 @@ -11,6 +11,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect @@ -116,6 +117,7 @@ private fun MapScreenContent( }, modifier = Modifier .align(Alignment.TopEnd) + .statusBarsPadding() .padding(top = 20.dp, end = 16.dp) ) diff --git a/app/src/main/kotlin/org/db3/airmq/features/navigation/AirMQNavGraph.kt b/app/src/main/kotlin/org/db3/airmq/features/navigation/AirMQNavGraph.kt index 71f7a23..23d67f7 100644 --- a/app/src/main/kotlin/org/db3/airmq/features/navigation/AirMQNavGraph.kt +++ b/app/src/main/kotlin/org/db3/airmq/features/navigation/AirMQNavGraph.kt @@ -1,11 +1,13 @@ package org.db3.airmq.features.navigation +import android.app.Activity import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.material3.Icon import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect import androidx.compose.runtime.getValue import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem @@ -13,6 +15,7 @@ import androidx.compose.material3.NavigationBarItemDefaults import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource @@ -25,6 +28,7 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument +import androidx.core.view.WindowCompat import org.db3.airmq.R import org.db3.airmq.features.city.CityScreen import org.db3.airmq.features.constructor.ChartConstructorScreen @@ -64,6 +68,12 @@ fun AirMQNavGraph(modifier: Modifier = Modifier) { val currentRoute = navBackStackEntry?.destination?.route val showBottomBar = currentRoute in tabRoutes + val view = LocalView.current + SideEffect { + val window = (view.context as? Activity)?.window ?: return@SideEffect + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !showBottomBar + } + Scaffold( modifier = modifier, contentWindowInsets = WindowInsets(0, 0, 0, 0),