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

Commit 2720d95c authored by Ellen Poe's avatar Ellen Poe
Browse files

Merge branch 'ellenhp/custom_navigation_view' into 'main'

Add new new navigation overlay views, enlarge navigation progress view text

Closes #77

See merge request e/os/cardinal!49
parents d78c17d6 15d2f177
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -110,7 +110,7 @@ import earth.maps.cardinal.routing.RouteRepository
import earth.maps.cardinal.ui.directions.DirectionsScreen
import earth.maps.cardinal.ui.directions.DirectionsViewModel
import earth.maps.cardinal.ui.directions.RouteDisplayHandler
import earth.maps.cardinal.ui.directions.TurnByTurnNavigationScreen
import earth.maps.cardinal.ui.navigation.TurnByTurnNavigationScreen
import earth.maps.cardinal.ui.home.HomeScreen
import earth.maps.cardinal.ui.home.HomeViewModel
import earth.maps.cardinal.ui.home.NearbyScreenContent
+150 −0
Original line number Diff line number Diff line
package earth.maps.cardinal.ui.navigation

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import com.stadiamaps.ferrostar.composeui.config.NavigationViewComponentBuilder
import com.stadiamaps.ferrostar.composeui.models.CameraControlState
import com.stadiamaps.ferrostar.composeui.theme.DefaultInstructionRowTheme
import com.stadiamaps.ferrostar.composeui.theme.DefaultRoadNameViewTheme
import com.stadiamaps.ferrostar.composeui.theme.InstructionRowTheme
import com.stadiamaps.ferrostar.composeui.theme.NavigationUITheme
import com.stadiamaps.ferrostar.composeui.theme.RoadNameViewTheme
import com.stadiamaps.ferrostar.composeui.theme.TripProgressViewStyle
import com.stadiamaps.ferrostar.composeui.theme.TripProgressViewTheme
import com.stadiamaps.ferrostar.composeui.views.components.CurrentRoadNameView
import com.stadiamaps.ferrostar.composeui.views.components.InstructionsView
import com.stadiamaps.ferrostar.composeui.views.components.TripProgressView
import com.stadiamaps.ferrostar.core.NavigationUiState
import kotlin.time.ExperimentalTime

object CardinalNavigationUITheme : NavigationUITheme {
    override val instructionRowTheme: InstructionRowTheme
        @Composable get() = DefaultInstructionRowTheme

    override val roadNameViewTheme: RoadNameViewTheme
        @Composable get() = DefaultRoadNameViewTheme

    override val tripProgressViewTheme: TripProgressViewTheme
        @Composable get() = CardinalTripProgressViewTheme

    override val buttonSize: DpSize
        @Composable get() = DpSize(56.dp, 56.dp)
}

object CardinalTripProgressViewTheme : TripProgressViewTheme {
    override val style: TripProgressViewStyle
        @Composable get() = TripProgressViewStyle.SIMPLIFIED

    override val measurementTextStyle: TextStyle
        @Composable
        get() =
            MaterialTheme.typography.titleLarge.copy(
                color = MaterialTheme.colorScheme.onSurface, fontWeight = FontWeight.Normal)

    override val secondaryTextStyle: TextStyle
        @Composable
        get() =
            MaterialTheme.typography.labelSmall.copy(color = MaterialTheme.colorScheme.onSurfaceVariant)

    override val exitIconColor: Color
        @Composable get() = MaterialTheme.colorScheme.onSecondary

    override val exitButtonBackgroundColor: Color
        @Composable get() = MaterialTheme.colorScheme.secondary

    override val backgroundColor: Color
        @Composable get() = MaterialTheme.colorScheme.surface
}


@Composable
fun CardinalInstructionsView(modifier: Modifier, uiState: NavigationUiState) {
    uiState.visualInstruction?.let { instructions ->
        InstructionsView(
            modifier = modifier,
            instructions = instructions,
            theme = CardinalNavigationUITheme.instructionRowTheme,
            remainingSteps = uiState.remainingSteps,
            distanceToNextManeuver = uiState.progress?.distanceToNextManeuver
        )
    }
}

@OptIn(ExperimentalTime::class)
@Composable
fun CardinalProgressView(
    modifier: Modifier,
    uiState: NavigationUiState,
    onTapExit: (() -> Unit)?
) {
    uiState.progress?.let { progress ->
        TripProgressView(
            modifier = modifier,
            theme = CardinalNavigationUITheme.tripProgressViewTheme,
            progress = progress,
            onTapExit = onTapExit
        )
    }
}

@Composable
fun CardinalRoadNameView(
    modifier: Modifier,
    roadName: String?,
    cameraControlState: CameraControlState
) {
    if (cameraControlState is CameraControlState.ShowRouteOverview) {
        roadName?.let { roadName ->
            Row(
                modifier.fillMaxWidth(),
                verticalAlignment = Alignment.Bottom,
                horizontalArrangement = Arrangement.Center
            ) {
                CurrentRoadNameView(
                    modifier = modifier,
                    theme = CardinalNavigationUITheme.roadNameViewTheme,
                    currentRoadName = roadName
                )

                Spacer(modifier = Modifier.height(8.dp))
            }
        }
    }
}

fun navigationViewComponentBuilder(): NavigationViewComponentBuilder {
    return NavigationViewComponentBuilder(
        instructionsView = @Composable { modifier, navigationUiState ->
            CardinalInstructionsView(
                modifier,
                navigationUiState
            )
        },
        progressView = @Composable { modifier, navigationUiState, onTapExit ->
            CardinalProgressView(
                modifier,
                navigationUiState,
                onTapExit
            )
        },
        roadNameView = @Composable { modifier, roadName, cameraControlState ->
            CardinalRoadNameView(
                modifier,
                roadName,
                cameraControlState
            )
        },
    )
}
+5 −2
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@
 *     along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package earth.maps.cardinal.ui.directions
package earth.maps.cardinal.ui.navigation

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
@@ -107,7 +107,10 @@ fun TurnByTurnNavigationScreen(
        // Only display the navigation view if we have a route
        if (route != null) {
            DynamicallyOrientingNavigationView(
                styleUrl = styleUrl, modifier = Modifier, viewModel = viewModel
                styleUrl = styleUrl,
                modifier = Modifier,
                viewModel = viewModel,
                views = navigationViewComponentBuilder()
            )
        } else {
            // Show a placeholder or loading state when no route is available
+1 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@
 *     along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package earth.maps.cardinal.ui.directions
package earth.maps.cardinal.ui.navigation

import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
package earth.maps.cardinal.ui.directions

import earth.maps.cardinal.routing.FerrostarWrapperRepository
import earth.maps.cardinal.ui.navigation.TurnByTurnNavigationViewModel
import io.mockk.mockk
import org.junit.Assert.assertEquals
import org.junit.Before