Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4315384a authored by Ellen Poe's avatar Ellen Poe
Browse files

Merge branch 'ellenhp/ui_bottom_cutoff' into 'main'

Add padding to bottom sheet to prevent ui cutoff

Closes #30

See merge request e/os/cardinal!53
parents c25bcfbb 2b38781d
Loading
Loading
Loading
Loading
Loading
+0 −56
Original line number Original line Diff line number Diff line
/*
 *     Cardinal Maps
 *     Copyright (C) 2025 Cardinal Maps Authors
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package earth.maps.cardinal.routing

data class RouteResult(
    val distance: Double, // in meters or as specified by units
    val duration: Double, // in seconds
    val legs: List<RouteLeg>,
    val geometry: RouteGeometry,
    val units: String = "kilometers" // or "miles"
)

data class RouteLeg(
    val summary: String,
    val distance: Double,
    val duration: Double,
    val steps: List<RouteStep>
)

data class RouteStep(
    val distance: Double,
    val duration: Double,
    val instruction: String,
    val name: String,
    val geometry: RouteGeometry,
)

data class RouteGeometry(
    val type: String = "LineString",
    val coordinates: List<List<Double>> // [longitude, latitude] pairs
)

data class Maneuver(
    val location: List<Double>, // [longitude, latitude]
    val bearingBefore: Double,
    val bearingAfter: Double,
    val type: String,
    val modifier: String? = null,
    val instruction: String
)
+10 −5
Original line number Original line Diff line number Diff line
@@ -547,7 +547,9 @@ private fun NearbyPoiRoute(
        rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState)
        rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState)


    CardinalAppScaffold(
    CardinalAppScaffold(
        scaffoldState = scaffoldState, peekHeight = state.screenHeightDp / 3,
        scaffoldState = scaffoldState,
        peekHeight = state.screenHeightDp / 3,
        showToolbar = true,
        content = {
        content = {
            NearbyScreenContent(viewModel = nearbyViewModel, onPlaceSelected = {
            NearbyScreenContent(viewModel = nearbyViewModel, onPlaceSelected = {
                NavigationUtils.navigate(navController, Screen.PlaceCard(it))
                NavigationUtils.navigate(navController, Screen.PlaceCard(it))
@@ -579,7 +581,9 @@ private fun NearbyTransitRoute(
        rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState)
        rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState)


    CardinalAppScaffold(
    CardinalAppScaffold(
        scaffoldState = scaffoldState, peekHeight = state.screenHeightDp / 3,
        scaffoldState = scaffoldState,
        peekHeight = state.screenHeightDp / 3,
        showToolbar = true,
        content = {
        content = {
            TransitScreenContent(viewModel = transitViewModel, onRouteClicked = {
            TransitScreenContent(viewModel = transitViewModel, onRouteClicked = {
                NavigationUtils.navigate(navController, Screen.PlaceCard(it))
                NavigationUtils.navigate(navController, Screen.PlaceCard(it))
@@ -834,6 +838,7 @@ private fun OfflineAreasRoute(
                    state.fabHeight = it
                    state.fabHeight = it
                }
                }
            },
            },
            showToolbar = true,
            content = { snackBarHostState ->
            content = { snackBarHostState ->
                OfflineAreasScreen(
                OfflineAreasScreen(
                    currentViewport = visibleRegion,
                    currentViewport = visibleRegion,
@@ -1240,6 +1245,7 @@ private fun HomeScreenComposable(
                onFabHeightChange(it)
                onFabHeightChange(it)
            }
            }
        },
        },
        showToolbar = true,
        content = {
        content = {
            HomeScreen(
            HomeScreen(
                viewModel = viewModel,
                viewModel = viewModel,
@@ -1306,7 +1312,7 @@ fun CardinalAppScaffold(
    peekHeight: Dp,
    peekHeight: Dp,
    content: @Composable (SnackbarHostState) -> Unit,
    content: @Composable (SnackbarHostState) -> Unit,
    fabHeightCallback: (Dp) -> Unit,
    fabHeightCallback: (Dp) -> Unit,
    showToolbar: Boolean = true,
    showToolbar: Boolean,
) {
) {
    val density = LocalDensity.current
    val density = LocalDensity.current
    val snackBarHostState = remember { SnackbarHostState() }
    val snackBarHostState = remember { SnackbarHostState() }
@@ -1326,7 +1332,7 @@ fun CardinalAppScaffold(
            sheetBackgroundColor = BottomSheetDefaults.ContainerColor,
            sheetBackgroundColor = BottomSheetDefaults.ContainerColor,
            sheetContent = {
            sheetContent = {
                Column(
                Column(
                    modifier = Modifier.onGloballyPositioned {
                    modifier = Modifier.padding(bottom = bottomPadding).onGloballyPositioned {
                        fabHeightCallback(with(density) { it.positionInRoot().y.toDp() })
                        fabHeightCallback(with(density) { it.positionInRoot().y.toDp() })
                    }) {
                    }) {
                    Box(
                    Box(
@@ -1338,7 +1344,6 @@ fun CardinalAppScaffold(
                    }
                    }
                    content(snackBarHostState)
                    content(snackBarHostState)
                }
                }
                Spacer(modifier = Modifier.height(bottomInset))
            },
            },
            content = {})
            content = {})
    }
    }
+11 −1
Original line number Original line Diff line number Diff line
@@ -25,10 +25,15 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Button
@@ -61,6 +66,7 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.stringResource
@@ -122,6 +128,10 @@ fun DirectionsScreen(


    val coroutineScope = rememberCoroutineScope()
    val coroutineScope = rememberCoroutineScope()


    val bottomPadding = with(LocalDensity.current) {
        WindowInsets.safeDrawing.getBottom(this).toDp()
    }

    LaunchedEffect(Unit) {
    LaunchedEffect(Unit) {
        // Run this in our coroutine scope rather than viewModelScope.
        // Run this in our coroutine scope rather than viewModelScope.
        viewModel.initializeRoutingMode()
        viewModel.initializeRoutingMode()
@@ -153,7 +163,7 @@ fun DirectionsScreen(
    Column(
    Column(
        modifier = Modifier
        modifier = Modifier
            .fillMaxSize()
            .fillMaxSize()
            .padding(horizontal = dimensionResource(dimen.padding))
            .padding(start = dimensionResource(dimen.padding), end = dimensionResource(dimen.padding), bottom = bottomPadding)
    ) {
    ) {
        if (isAnyFieldFocused) {
        if (isAnyFieldFocused) {
            DirectionsScreenFocusedField(
            DirectionsScreenFocusedField(
+8 −1
Original line number Original line Diff line number Diff line
@@ -25,10 +25,12 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyColumn
@@ -52,6 +54,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.stringResource
@@ -71,10 +74,14 @@ fun NearbyScreenContent(viewModel: NearbyViewModel, onPlaceSelected: (Place) ->
    val error by viewModel.error.collectAsState()
    val error by viewModel.error.collectAsState()
    val addressFormatter = remember { AddressFormatter() }
    val addressFormatter = remember { AddressFormatter() }


    val bottomPadding = with(LocalDensity.current) {
        WindowInsets.safeDrawing.getBottom(this).toDp()
    }

    Column(
    Column(
        modifier = Modifier
        modifier = Modifier
            .fillMaxSize()
            .fillMaxSize()
            .padding(horizontal = dimensionResource(dimen.padding))
            .padding(start = dimensionResource(dimen.padding), end = dimensionResource(dimen.padding), bottom = bottomPadding)
            .onGloballyPositioned { coordinates ->
            .onGloballyPositioned { coordinates ->
                // This would normally update peek height, but for nearby content
                // This would normally update peek height, but for nearby content
                // we don't need special peek height management like other screens
                // we don't need special peek height management like other screens
+8 −1
Original line number Original line Diff line number Diff line
@@ -32,10 +32,12 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.HorizontalPager
@@ -60,6 +62,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.stringResource
@@ -99,6 +102,10 @@ fun TransitScreenContent(
    val departures by viewModel.departures.collectAsState(emptyList())
    val departures by viewModel.departures.collectAsState(emptyList())
    val use24HourFormat by viewModel.use24HourFormat.collectAsState()
    val use24HourFormat by viewModel.use24HourFormat.collectAsState()


    val bottomPadding = with(LocalDensity.current) {
        WindowInsets.safeDrawing.getBottom(this).toDp()
    }

    LaunchedEffect(secondsSinceStart) {
    LaunchedEffect(secondsSinceStart) {
        if (secondsSinceStart % 30 == 0 && secondsSinceStart > 0) {
        if (secondsSinceStart % 30 == 0 && secondsSinceStart > 0) {
            viewModel.refreshData()
            viewModel.refreshData()
@@ -112,7 +119,7 @@ fun TransitScreenContent(
            .padding(
            .padding(
                start = dimensionResource(dimen.padding),
                start = dimensionResource(dimen.padding),
                end = dimensionResource(dimen.padding),
                end = dimensionResource(dimen.padding),
                bottom = 36.dp
                bottom = bottomPadding,
            )
            )
    ) {
    ) {
        DeparturesHeader(viewModel, coroutineScope, isRefreshingDepartures.value)
        DeparturesHeader(viewModel, coroutineScope, isRefreshingDepartures.value)