Skip to content

Commit

Permalink
Feat/android/view refactor (#356)
Browse files Browse the repository at this point in the history
* feat: view refactor & cleanup

* feat: refactoring views for better reuse, easier config and more general purpose features

* feat: in progressing setting up basics for car play

* Apply automatic changes

* feat: in progressing setting up basics for car play

* feat: improved android view config and setup, current road name and showcase route:

* feat: improved android view config and setup, current road name and showcase route:

* feat: improved android view config and setup, current road name and showcase route:

* feat: improved android view config and setup, current road name and showcase route:

---------

Co-authored-by: Archdoog <[email protected]>
  • Loading branch information
Archdoog and Archdoog authored Nov 13, 2024
1 parent f5790e2 commit 12a6f19
Show file tree
Hide file tree
Showing 41 changed files with 620 additions and 444 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.stadiamaps.ferrostar.composeui.config

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.BoxScope
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.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.stadiamaps.ferrostar.composeui.models.CameraControlState
import com.stadiamaps.ferrostar.composeui.theme.DefaultNavigationUITheme
import com.stadiamaps.ferrostar.composeui.theme.NavigationUITheme
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

data class NavigationViewComponentBuilder(
val instructionsView: @Composable (modifier: Modifier, uiState: NavigationUiState) -> Unit,
val progressView:
@Composable
(modifier: Modifier, uiState: NavigationUiState, onTapExit: (() -> Unit)?) -> Unit,
val streetNameView:
@Composable
(modifier: Modifier, roadName: String?, cameraControlState: CameraControlState) -> Unit,
val customOverlayView: @Composable (BoxScope.(Modifier) -> Unit)? = null,
// TODO: We may reasonably be able to add the NavigationMapView here. But not sure how much
// value that would add
// since most of the hard config already exists within the overlay views which are not
// maplibre specific.
) {
companion object {
fun Default(theme: NavigationUITheme = DefaultNavigationUITheme) =
NavigationViewComponentBuilder(
instructionsView = { modifier, uiState ->
uiState.visualInstruction?.let { instructions ->
InstructionsView(
modifier = modifier,
instructions = instructions,
theme = theme.instructionRowTheme,
remainingSteps = uiState.remainingSteps,
distanceToNextManeuver = uiState.progress?.distanceToNextManeuver)
}
},
progressView = { modifier, uiState, onTapExit ->
uiState.progress?.let { progress ->
TripProgressView(
modifier = modifier,
theme = theme.tripProgressViewTheme,
progress = progress,
onTapExit = onTapExit)
}
},
streetNameView = { modifier, roadName, cameraControlState ->
if (cameraControlState is CameraControlState.ShowRouteOverview) {
roadName?.let { roadName ->
Row(
modifier.fillMaxWidth(),
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.Center) {
CurrentRoadNameView(
modifier = modifier,
theme = theme.roadNameViewTheme,
currentRoadName = roadName)

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

fun NavigationViewComponentBuilder.withInstructionsView(
instructionsView: @Composable (modifier: Modifier, uiState: NavigationUiState) -> Unit
): NavigationViewComponentBuilder {
return copy(instructionsView = instructionsView)
}

fun NavigationViewComponentBuilder.withProgressView(
progressView:
@Composable
(modifier: Modifier, uiState: NavigationUiState, onTapExit: (() -> Unit)?) -> Unit
): NavigationViewComponentBuilder {
return copy(progressView = progressView)
}

fun NavigationViewComponentBuilder.withStreetNameView(
streetNameView:
@Composable
(modifier: Modifier, roadName: String?, cameraControlState: CameraControlState) -> Unit
): NavigationViewComponentBuilder {
return copy(streetNameView = streetNameView)
}

fun NavigationViewComponentBuilder.withCustomOverlayView(
customOverlayView: @Composable (BoxScope.(Modifier) -> Unit)
): NavigationViewComponentBuilder {
return copy(customOverlayView = customOverlayView)
}
Original file line number Diff line number Diff line change
@@ -1,40 +1,29 @@
package com.stadiamaps.ferrostar.composeui.config

import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp

sealed class CameraControlState {
data object Hidden : CameraControlState()

data class ShowRecenter(val updateCamera: () -> Unit) : CameraControlState()

data class ShowRouteOverview(val updateCamera: () -> Unit) : CameraControlState()
}

data class VisualNavigationViewConfig(
// Mute
var showMute: Boolean = false,
var onMute: (() -> Unit)? = null,

// Zoom
var showZoom: Boolean = false,
var buttonSize: DpSize = DpSize(56.dp, 56.dp)
var onZoomIn: (() -> Unit)? = null,
var onZoomOut: (() -> Unit)? = null,
) {
companion object {
fun Default() = VisualNavigationViewConfig(showMute = true, showZoom = true)
}
}

/** Enables the mute button in the navigation view. */
fun VisualNavigationViewConfig.useMuteButton(): VisualNavigationViewConfig {
showMute = true
return this
fun VisualNavigationViewConfig.useMuteButton(onMute: () -> Unit): VisualNavigationViewConfig {
return copy(showMute = true, onMute = onMute)
}

/** Enables the zoom button in the navigation view. */
fun VisualNavigationViewConfig.useZoomButton(): VisualNavigationViewConfig {
showZoom = true
return this
}

/** Changes the size of navigation buttons. */
fun VisualNavigationViewConfig.buttonSize(size: DpSize): VisualNavigationViewConfig {
buttonSize = size
return this
fun VisualNavigationViewConfig.useZoomButton(
onZoomIn: () -> Unit,
onZoomOut: () -> Unit
): VisualNavigationViewConfig {
return copy(showZoom = true, onZoomIn = onZoomIn, onZoomOut = onZoomOut)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.stadiamaps.ferrostar.composeui.models

sealed class CameraControlState {
data object Hidden : CameraControlState()

data class ShowRecenter(val updateCamera: () -> Unit) : CameraControlState()

data class ShowRouteOverview(val updateCamera: () -> Unit) : CameraControlState()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.stadiamaps.ferrostar.composeui.models

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp

data class NavigationViewMetrics(
val progressViewSize: DpSize = DpSize(0.dp, 0.dp),
val instructionsViewSize: DpSize = DpSize(0.dp, 0.dp),
val buttonSize: DpSize,
) {

/**
* Returns the MapView's safe insets.
*
* @param start Optional additional start padding. Default is 0.dp.
* @param top Optional additional top padding. Default is instructionsViewSize.height.
* @param end Optional additional end padding. Default is 0.dp.
* @param bottom Optional additional bottom padding. Default is progressViewSize.height.
* @return The calculated padding insets.
*/
fun mapViewInsets(
start: Dp = 0.dp,
top: Dp = 0.dp,
end: Dp = 0.dp,
bottom: Dp = 0.dp,
): PaddingValues {
return PaddingValues(
start = start,
top = instructionsViewSize.height + top,
end = end,
bottom = progressViewSize.height + buttonSize.height + bottom,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import com.stadiamaps.ferrostar.composeui.formatting.DurationFormatter
import com.stadiamaps.ferrostar.composeui.formatting.EstimatedArrivalDateTimeFormatter
import com.stadiamaps.ferrostar.composeui.formatting.LocalizedDistanceFormatter
import com.stadiamaps.ferrostar.composeui.formatting.LocalizedDurationFormatter
import com.stadiamaps.ferrostar.composeui.views.maneuver.maneuverIcon
import com.stadiamaps.ferrostar.composeui.views.components.maneuver.maneuverIcon
import com.stadiamaps.ferrostar.core.extensions.estimatedArrivalTime
import com.stadiamaps.ferrostar.core.service.ForegroundNotificationBuilder
import uniffi.ferrostar.TripProgress
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ object DefaultInstructionRowTheme : InstructionRowTheme {
@Composable get() = MaterialTheme.colorScheme.onSurface

override val backgroundColor: Color
@Composable get() = MaterialTheme.colorScheme.surfaceContainerLow
@Composable get() = MaterialTheme.colorScheme.surface
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.stadiamaps.ferrostar.composeui.theme

import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp

interface NavigationUITheme {
@get:Composable val instructionRowTheme: InstructionRowTheme
@get:Composable val roadNameViewTheme: RoadNameViewTheme
@get:Composable val tripProgressViewTheme: TripProgressViewTheme
@get:Composable val buttonSize: DpSize
}

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

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

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

override val buttonSize: DpSize
@Composable get() = DpSize(56.dp, 56.dp)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.stadiamaps.ferrostar.composeui.views
package com.stadiamaps.ferrostar.composeui.views.components

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.stadiamaps.ferrostar.composeui.views
package com.stadiamaps.ferrostar.composeui.views.components

import android.icu.util.ULocale
import androidx.compose.animation.animateContentSize
Expand All @@ -20,7 +20,6 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
Expand All @@ -36,9 +35,9 @@ import com.stadiamaps.ferrostar.composeui.formatting.DistanceFormatter
import com.stadiamaps.ferrostar.composeui.formatting.LocalizedDistanceFormatter
import com.stadiamaps.ferrostar.composeui.theme.DefaultInstructionRowTheme
import com.stadiamaps.ferrostar.composeui.theme.InstructionRowTheme
import com.stadiamaps.ferrostar.composeui.views.controls.PillDragHandle
import com.stadiamaps.ferrostar.composeui.views.maneuver.ManeuverImage
import com.stadiamaps.ferrostar.composeui.views.maneuver.ManeuverInstructionView
import com.stadiamaps.ferrostar.composeui.views.components.controls.PillDragHandle
import com.stadiamaps.ferrostar.composeui.views.components.maneuver.ManeuverImage
import com.stadiamaps.ferrostar.composeui.views.components.maneuver.ManeuverInstructionView
import uniffi.ferrostar.ManeuverModifier
import uniffi.ferrostar.ManeuverType
import uniffi.ferrostar.RouteStep
Expand All @@ -62,11 +61,12 @@ fun InstructionsView(
remainingSteps: List<RouteStep>? = null,
initExpanded: Boolean = false,
contentBuilder: @Composable (VisualInstruction) -> Unit = {
ManeuverImage(it.primaryContent, tint = MaterialTheme.colorScheme.primary)
ManeuverImage(it.primaryContent, tint = theme.iconTintColor)
}
) {
var isExpanded by remember { mutableStateOf(initExpanded) }
val screenHeight = LocalConfiguration.current.screenHeightDp.dp
val remainingSteps: List<RouteStep> = remainingSteps?.drop(1) ?: emptyList()

Box(
modifier =
Expand All @@ -89,7 +89,7 @@ fun InstructionsView(
// TODO: Secondary content

// Expanded content
val showMultipleRows = isExpanded && remainingSteps != null && remainingSteps.count() > 1
val showMultipleRows = isExpanded && remainingSteps.count() > 1
if (showMultipleRows) {
Spacer(modifier = Modifier.height(8.dp))
HorizontalDivider(thickness = 1.dp)
Expand All @@ -101,19 +101,17 @@ fun InstructionsView(
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(8.dp)) {
if (remainingSteps != null) {
items(remainingSteps.drop(1)) { step ->
step.visualInstructions.firstOrNull()?.let { upcomingInstruction ->
ManeuverInstructionView(
text = upcomingInstruction.primaryContent.text,
distanceFormatter = distanceFormatter,
distanceToNextManeuver = step.distance,
theme = theme) {
contentBuilder(upcomingInstruction)
}
Spacer(modifier = Modifier.height(8.dp))
HorizontalDivider(thickness = 1.dp)
}
items(remainingSteps) { step ->
step.visualInstructions.firstOrNull()?.let { upcomingInstruction ->
ManeuverInstructionView(
text = upcomingInstruction.primaryContent.text,
distanceFormatter = distanceFormatter,
distanceToNextManeuver = step.distance,
theme = theme) {
contentBuilder(upcomingInstruction)
}
Spacer(modifier = Modifier.height(8.dp))
HorizontalDivider(thickness = 1.dp)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.stadiamaps.ferrostar.composeui.views
package com.stadiamaps.ferrostar.composeui.views.components

import android.icu.util.ULocale
import androidx.compose.foundation.background
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.stadiamaps.ferrostar.composeui.views.controls
package com.stadiamaps.ferrostar.composeui.views.components.controls

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.stadiamaps.ferrostar.composeui.views.controls
package com.stadiamaps.ferrostar.composeui.views.components.controls

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.stadiamaps.ferrostar.composeui.views.controls
package com.stadiamaps.ferrostar.composeui.views.components.controls

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
Expand Down Expand Up @@ -30,7 +30,7 @@ fun PillDragHandle(
toggle: () -> Unit = {}
) {
val handleHeight = if (isExpanded) 36.dp else 4.dp
Box(modifier = modifier.height(handleHeight).clickable(onClick = toggle)) {
Box(modifier = modifier.fillMaxWidth().height(handleHeight).clickable(onClick = toggle)) {
if (isExpanded) {
Icon(
Icons.Rounded.KeyboardArrowUp,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.stadiamaps.ferrostar.composeui.views.gridviews
package com.stadiamaps.ferrostar.composeui.views.components.gridviews

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
Expand Down
Loading

0 comments on commit 12a6f19

Please sign in to comment.