Skip to content

Commit

Permalink
Fix/android/view builder and speed json (#360)
Browse files Browse the repository at this point in the history
* fix: some minor fixes for easier customization

* Apply automatic changes

* fix: some minor fixes for easier customization

* Apply automatic changes

* fix: some minor fixes for easier customization

* fix: minor improvements for view builder, fix for valhalla speed unit, and demo app update.

* fix: minor improvements for view builder, fix for valhalla speed unit, and demo app update.

* added try catch to annotation parser, renamed uiState to navigationUiState

* added try catch to annotation parser, renamed uiState to navigationUiState

---------

Co-authored-by: Archdoog <[email protected]>
  • Loading branch information
Archdoog and Archdoog authored Nov 19, 2024
1 parent d9a79cb commit e1b6235
Show file tree
Hide file tree
Showing 13 changed files with 38 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ 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:
internal val instructionsView:
@Composable
(modifier: Modifier, uiState: NavigationUiState) -> Unit,
internal val progressView:
@Composable
(modifier: Modifier, uiState: NavigationUiState, onTapExit: (() -> Unit)?) -> Unit,
val streetNameView:
internal val streetNameView:
@Composable
(modifier: Modifier, roadName: String?, cameraControlState: CameraControlState) -> Unit,
val customOverlayView: @Composable (BoxScope.(Modifier) -> Unit)? = null,
internal 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
Expand Down Expand Up @@ -72,6 +74,8 @@ data class NavigationViewComponentBuilder(
}
})
}

fun getCustomOverlayView(): @Composable (BoxScope.(Modifier) -> Unit)? = customOverlayView
}

fun NavigationViewComponentBuilder.withInstructionsView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ fun LandscapeNavigationOverlayView(
val windowInsets = WindowInsets.statusBars.asPaddingValues()
val halfOfScreen: Dp = with(density) { LocalConfiguration.current.screenWidthDp.dp / 2 }

val uiState by viewModel.uiState.collectAsState()
val uiState by viewModel.navigationUiState.collectAsState()

var instructionsViewSize by remember { mutableStateOf(DpSize.Zero) }
var progressViewSize by remember { mutableStateOf(DpSize.Zero) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fun PortraitNavigationOverlayView(
val density = LocalDensity.current
val windowInsets = WindowInsets.statusBars.asPaddingValues()

val uiState by viewModel.uiState.collectAsState()
val uiState by viewModel.navigationUiState.collectAsState()

var instructionsViewSize by remember { mutableStateOf(DpSize.Zero) }
var progressViewSize by remember { mutableStateOf(DpSize.Zero) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ data class NavigationUiState(
}

interface NavigationViewModel {
val uiState: StateFlow<NavigationUiState>
val navigationUiState: StateFlow<NavigationUiState>

fun toggleMute()

Expand All @@ -112,7 +112,7 @@ open class DefaultNavigationViewModel(
private val muteState: StateFlow<Boolean?> =
ferrostarCore.spokenInstructionObserver?.muteState ?: MutableStateFlow(null)

override val uiState =
override val navigationUiState =
combine(ferrostarCore.state, muteState) { a, b -> a to b }
.map { (coreState, muteState) -> annotationPublisher.map(coreState) to muteState }
.map { (stateWrapper, muteState) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import uniffi.ferrostar.TripState
class DefaultAnnotationPublisher<T>(
private val adapter: JsonAdapter<T>,
private val speedLimitMapper: (T?) -> Speed?,
private val onError: ((Throwable) -> Unit)? = null
) : AnnotationPublisher<T> {

override fun map(state: NavigationState): AnnotationWrapper<T> {
Expand All @@ -16,10 +17,10 @@ class DefaultAnnotationPublisher<T>(

private fun decodeAnnotations(state: NavigationState): T? {
return if (state.tripState is TripState.Navigating) {
val json = state.tripState.annotationJson
if (json != null) {
adapter.fromJson(json)
} else {
try {
state.tripState.annotationJson?.let { adapter.fromJson(it) }
} catch (e: Exception) {
onError?.invoke(e)
null
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SpeedSerializationAdapter : JsonAdapter<Speed>() {
is Speed.NoLimit -> writer.name("none").value(true)
is Speed.Unknown -> writer.name("unknown").value(true)
is Speed.Value ->
writer.name("value").value(speed.value).name("unit").value(speed.unit.text)
writer.name("speed").value(speed.value).name("unit").value(speed.unit.text)
}
writer.endObject()
}
Expand All @@ -33,7 +33,7 @@ class SpeedSerializationAdapter : JsonAdapter<Speed>() {
var unit: String? = null

while (reader.hasNext()) {
when (reader.selectName(JsonReader.Options.of("none", "unknown", "value", "unit"))) {
when (reader.selectName(JsonReader.Options.of("none", "unknown", "speed", "unit"))) {
0 -> none = reader.nextBoolean()
1 -> unknown = reader.nextBoolean()
2 -> value = reader.nextDouble()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ fun valhallaExtendedOSRMAnnotationPublisher(): AnnotationPublisher<ValhallaOSRME
val moshi =
Moshi.Builder().add(SpeedSerializationAdapter()).add(KotlinJsonAdapterFactory()).build()
val adapter = moshi.adapter(ValhallaOSRMExtendedAnnotation::class.java)
return DefaultAnnotationPublisher<ValhallaOSRMExtendedAnnotation>(adapter) { it?.speedLimit }
return DefaultAnnotationPublisher<ValhallaOSRMExtendedAnnotation>(
adapter, speedLimitMapper = { it?.speedLimit })
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ fun NavigationUiState.Companion.pedestrianExample(): NavigationUiState =
UserLocation.pedestrianExample(),
UserLocation.pedestrianExample())

class MockNavigationViewModel(override val uiState: StateFlow<NavigationUiState>) :
class MockNavigationViewModel(override val navigationUiState: StateFlow<NavigationUiState>) :
ViewModel(), NavigationViewModel {
override fun toggleMute() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ fun DemoNavigationScene(
Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)
}

val vmState by viewModel.uiState.collectAsState(scope.coroutineContext)
val navigationUiState by viewModel.navigationUiState.collectAsState(scope.coroutineContext)

val permissionsLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
Expand Down Expand Up @@ -88,7 +88,7 @@ fun DemoNavigationScene(
}

// For smart casting
val loc = vmState.location
val loc = navigationUiState.location
if (loc == null) {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Text("Waiting to acquire your GPS location...", modifier = Modifier.padding(innerPadding))
Expand All @@ -113,7 +113,7 @@ fun DemoNavigationScene(
AutocompleteOverlay(
modifier = modifier,
scope = scope,
isNavigating = vmState.isNavigating(),
isNavigating = navigationUiState.isNavigating(),
locationProvider = locationProvider,
loc = loc)
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.stadiamaps.ferrostar

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.stadiamaps.ferrostar.core.DefaultNavigationViewModel
import com.stadiamaps.ferrostar.core.FerrostarCore
import com.stadiamaps.ferrostar.core.LocationProvider
import com.stadiamaps.ferrostar.core.LocationUpdateListener
import com.stadiamaps.ferrostar.core.NavigationUiState
import com.stadiamaps.ferrostar.core.NavigationViewModel
import com.stadiamaps.ferrostar.core.annotation.AnnotationPublisher
import com.stadiamaps.ferrostar.core.annotation.valhalla.valhallaExtendedOSRMAnnotationPublisher
import com.stadiamaps.ferrostar.core.isNavigating
import java.util.concurrent.Executors
import kotlinx.coroutines.flow.MutableStateFlow
Expand All @@ -23,8 +24,9 @@ import uniffi.ferrostar.UserLocation

class DemoNavigationViewModel(
// This is a simple example, but these would typically be dependency injected
private val ferrostarCore: FerrostarCore = AppModule.ferrostarCore,
) : ViewModel(), LocationUpdateListener, NavigationViewModel {
val ferrostarCore: FerrostarCore = AppModule.ferrostarCore,
annotationPublisher: AnnotationPublisher<*> = valhallaExtendedOSRMAnnotationPublisher()
) : DefaultNavigationViewModel(ferrostarCore, annotationPublisher), LocationUpdateListener {
private val locationStateFlow = MutableStateFlow<UserLocation?>(null)
private val executor = Executors.newSingleThreadScheduledExecutor()

Expand All @@ -40,7 +42,7 @@ class DemoNavigationViewModel(
locationProvider.removeListener(this)
}

override val uiState: StateFlow<NavigationUiState> =
override val navigationUiState: StateFlow<NavigationUiState> =
combine(ferrostarCore.state, muteState, locationStateFlow) { a, b, c -> Triple(a, b, c) }
.map { (ferrostarCoreState, isMuted, userLocation) ->
if (ferrostarCoreState.isNavigating()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ fun DynamicallyOrientingNavigationView(
// Maintain the actual size of the progress view for dynamic layout purposes.
val rememberProgressViewSize = remember { mutableStateOf(DpSize.Zero) }
val progressViewSize by rememberProgressViewSize
val uiState by viewModel.uiState.collectAsState()
val uiState by viewModel.navigationUiState.collectAsState()

// Get the correct padding based on edge-to-edge status.
val gridPadding = paddingForGridView()
Expand Down Expand Up @@ -140,7 +140,7 @@ fun DynamicallyOrientingNavigationView(
}
}

views.customOverlayView?.let { customOverlayView ->
views.getCustomOverlayView()?.let { customOverlayView ->
customOverlayView(Modifier.windowInsetsPadding(WindowInsets.systemBars).padding(gridPadding))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ fun LandscapeNavigationView(
onTapExit: (() -> Unit)? = null,
mapContent: @Composable @MapLibreComposable() ((NavigationUiState) -> Unit)? = null,
) {
val uiState by viewModel.uiState.collectAsState()
val uiState by viewModel.navigationUiState.collectAsState()

// Get the correct padding based on edge-to-edge status.
val gridPadding = paddingForGridView()
Expand Down Expand Up @@ -112,7 +112,7 @@ fun LandscapeNavigationView(
mapViewInsets = mapViewInsets,
onTapExit = onTapExit)

views.customOverlayView?.let { customOverlayView ->
views.getCustomOverlayView()?.let { customOverlayView ->
customOverlayView(Modifier.windowInsetsPadding(WindowInsets.systemBars).padding(gridPadding))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fun PortraitNavigationView(
onTapExit: (() -> Unit)? = null,
mapContent: @Composable @MapLibreComposable() ((NavigationUiState) -> Unit)? = null,
) {
val uiState by viewModel.uiState.collectAsState()
val uiState by viewModel.navigationUiState.collectAsState()

LaunchedEffect(mapViewInsets.value) {
Log.d("PortraitNavigationView", "mapViewInsets.value: ${mapViewInsets.value}")
Expand Down Expand Up @@ -123,7 +123,7 @@ fun PortraitNavigationView(
mapViewInsets = mapViewInsets,
onTapExit = onTapExit)

views.customOverlayView?.let { customOverlayView ->
views.getCustomOverlayView()?.let { customOverlayView ->
customOverlayView(
Modifier.windowInsetsPadding(WindowInsets.systemBars).padding(gridPadding))
}
Expand Down

0 comments on commit e1b6235

Please sign in to comment.