-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix/android/view builder and speed json #360
Conversation
…id/view-builder-and-speed-json
…, and demo app update.
…, and demo app update.
@@ -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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ahmedre I believe the actual key should be "speed"
when there's a value. E.g.
{
"speed": 56,
"unit": "km/h"
},
Let me know if there are additional cases. Definitely a bit of an obnoxious json object 😄.
Also, do we want to try catch the annotations parsing? On iOS we just convert a json parsing error to nil/null for annotations and an onError callback so that developers can log the failure. We figured better to let navigation succeed even in the case of a degraded/malformed annotations. See
ferrostar/apple/Sources/FerrostarCore/Annotations/AnnotationPublisher.swift
Lines 70 to 75 in 61e299a
do { | |
return try decoder.decode(Annotation.self, from: data) | |
} catch { | |
onError(error) | |
return nil | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, you are right - my mistake! agree re: try/catching the parsing with an error callback 👍
...ui/src/main/java/com/stadiamaps/ferrostar/composeui/config/NavigationViewComponentBuilder.kt
Show resolved
Hide resolved
@@ -24,7 +25,8 @@ 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 { | |||
annotationPublisher: AnnotationPublisher<*> = valhallaExtendedOSRMAnnotationPublisher() | |||
) : DefaultNavigationViewModel(ferrostarCore, annotationPublisher), LocationUpdateListener { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ianthetechie now that this view model uses the DefaultNavigationViewModel
. We should be able to refactor it to use the existing uiState from ferrostar and implement its own additional state for things like route loading, etc. Just to highlight how easy it is to customize without interrupting the default navigation behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me but I'll wait for @ahmedre to comment since he may have an opinion based on what they're building 👍
On the We can swap If we want to go this route, should we consider making |
) : ViewModel(), NavigationViewModel { | ||
|
||
private val muteState: StateFlow<Boolean?> = | ||
ferrostarCore.spokenInstructionObserver?.muteState ?: MutableStateFlow(null) | ||
|
||
override val uiState = | ||
override val navigationUiState = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ahmedre based on your comment, I've renamed this to navigationUiState
. My thought was most of the time a developer will just pass navigationUiState
into whatever NavigationView
they're using from ferrostar. If they want additional custom ui state, they now have access to common name and can even merge in navigationUiState
into their custom state. A custom view model may look something like this:
class NavViewModel(
val ferrostarCore: FerrostarCore,
val annotationPublisher: AnnotationPublisher<ValhallaOSRMExtendedAnnotation>
) : DefaultNavigationViewModel(ferrostarCore, annotationPublisher) {
// your own custom uiState can also be added to use alongside or merged with the navigationUiState.
val speed = navigationUiState
.map { navigationUiState ->
val metersPerSecond = navigationUiState.location?.speed?.value
metersPerSecond?.let {
return@map MeasurementSpeed(it, SpeedUnit.MetersPerSecond)
}
return@map null
}
fun addStop(latitude: Double, longitude: Double, name: String) {
viewModelScope.launch {
val userLocation = uiState.value.location ?: return@launch
val nextWaypoint = Waypoint(
coordinate = GeographicCoordinate(latitude, longitude),
kind = WaypointKind.BREAK
)
val routes = ferrostarCore.getRoutes(userLocation, listOf(nextWaypoint))
ferrostarCore.startNavigation(routes.first())
}
}
}
if (json != null) { | ||
adapter.fromJson(json) | ||
} else { | ||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now try catch and pass null when the serialization fails.
This looks good to me; going to merge now but happy to discuss other ways to make things clearer on today's call @ahmedre |
DefaultNavigationViewModel
SpeedUnit