Skip to content
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

Initial draft of adding TypeScript types #181

Merged
merged 11 commits into from
Oct 8, 2024
Merged
175 changes: 114 additions & 61 deletions common/Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions common/ferrostar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ getrandom = { version = "0.2.15", optional = true }
wasm-bindgen = { version = "0.2.93", optional = true }
web-time = { version = "1.1.0", features = ["serde"], optional = true }
itertools = "0.13.0"
tsify = { version = "0.4.5", default-features = false, features = ["js"] }

[build-dependencies]
uniffi = { workspace = true, features = ["build"] }
Expand Down
8 changes: 6 additions & 2 deletions common/ferrostar/src/deviation_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use geo::Point;

#[cfg(feature = "wasm-bindgen")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "wasm-bindgen")]
use tsify::Tsify;

#[cfg(test)]
use {
Expand All @@ -39,7 +41,8 @@ use web_time::SystemTime;
/// Determines if the user has deviated from the expected route.
#[derive(Clone)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[cfg_attr(feature = "wasm-bindgen", derive(Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Deserialize, Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(from_wasm_abi))]
pub enum RouteDeviationTracking {
/// No checks will be done, and we assume the user is always following the route.
None,
Expand Down Expand Up @@ -111,7 +114,8 @@ impl RouteDeviationTracking {
/// For example, we could conceivably add a "wrong way" status in the future.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[cfg_attr(feature = "wasm-bindgen", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Serialize, Deserialize, Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub enum RouteDeviation {
/// The user is proceeding on course within the expected tolerances; everything is normal.
NoDeviation,
Expand Down
1 change: 1 addition & 0 deletions common/ferrostar/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub mod navigation_controller;
pub mod routing_adapters;
pub mod simulation;

#[cfg(feature = "uniffi")]
use models::Route;
#[cfg(feature = "uniffi")]
use routing_adapters::{
Expand Down
32 changes: 32 additions & 0 deletions common/ferrostar/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ use std::time::SystemTime;
#[cfg(feature = "web-time")]
use web_time::SystemTime;

#[cfg(feature = "wasm-bindgen")]
use tsify::Tsify;

use std::collections::HashMap;
use uuid::Uuid;

Expand All @@ -41,6 +44,8 @@ pub enum ModelError {
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct GeographicCoordinate {
/// The latitude (in degrees).
pub lat: f64,
Expand Down Expand Up @@ -95,6 +100,8 @@ impl From<GeographicCoordinate> for Point {
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct Waypoint {
pub coordinate: GeographicCoordinate,
pub kind: WaypointKind,
Expand All @@ -104,6 +111,8 @@ pub struct Waypoint {
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub enum WaypointKind {
/// Starts or ends a leg of the trip.
///
Expand All @@ -117,6 +126,8 @@ pub enum WaypointKind {
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct BoundingBox {
/// The southwest corner of the bounding box.
pub sw: GeographicCoordinate,
Expand Down Expand Up @@ -149,6 +160,8 @@ pub struct Heading {
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct CourseOverGround {
/// The direction in which the user's device is traveling, measured in clockwise degrees from
/// true north (N = 0, E = 90, S = 180, W = 270).
Expand All @@ -167,6 +180,8 @@ impl CourseOverGround {
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct Speed {
/// The user's speed in meters per second.
pub value: f64,
Expand Down Expand Up @@ -215,6 +230,8 @@ mod system_time_format {
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct UserLocation {
pub coordinates: GeographicCoordinate,
/// The estimated accuracy of the coordinate (in meters)
Expand All @@ -239,6 +256,8 @@ impl From<UserLocation> for Point {
#[derive(Clone, Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct Route {
pub geometry: Vec<GeographicCoordinate>,
pub bbox: BoundingBox,
Expand Down Expand Up @@ -270,6 +289,8 @@ fn get_route_polyline(route: &Route, precision: u32) -> Result<String, ModelErro
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct RouteStep {
/// The full route geometry for this step.
pub geometry: Vec<GeographicCoordinate>,
Expand Down Expand Up @@ -351,6 +372,8 @@ impl RouteStep {
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi))]
pub struct SpokenInstruction {
/// Plain-text instruction which can be synthesized with a TTS engine.
pub text: String,
Expand All @@ -367,6 +390,7 @@ pub struct SpokenInstruction {
/// NOTE: While it is possible to deterministically create UUIDs, we do not do so at this time.
/// This should be theoretically possible though if someone cares to write up a proposal and a PR.
#[cfg_attr(test, serde(skip_serializing))]
#[cfg_attr(feature = "wasm-bindgen", tsify(type = "string"))]
pub utterance_id: Uuid,
}

Expand All @@ -376,6 +400,8 @@ pub struct SpokenInstruction {
#[derive(Deserialize, Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[cfg_attr(any(test, feature = "wasm-bindgen"), derive(Serialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
#[serde(rename_all = "lowercase")]
pub enum ManeuverType {
Turn,
Expand Down Expand Up @@ -407,6 +433,8 @@ pub enum ManeuverType {
#[derive(Deserialize, Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[cfg_attr(any(test, feature = "wasm-bindgen"), derive(Serialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
#[serde(rename_all = "lowercase")]
pub enum ManeuverModifier {
UTurn,
Expand All @@ -428,6 +456,8 @@ pub enum ManeuverModifier {
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct VisualInstructionContent {
/// The text to display.
pub text: String,
Expand All @@ -448,6 +478,8 @@ pub struct VisualInstructionContent {
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct VisualInstruction {
/// The primary instruction content.
///
Expand Down
17 changes: 12 additions & 5 deletions common/ferrostar/src/navigation_controller/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ use alloc::vec::Vec;
use geo::LineString;
#[cfg(feature = "wasm-bindgen")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "wasm-bindgen")]
use tsify::Tsify;

/// High-level state describing progress through a route.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(feature = "wasm-bindgen", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Serialize, Deserialize, Tsify))]
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct TripProgress {
/// The distance to the next maneuver, in meters.
pub distance_to_next_maneuver: f64,
Expand All @@ -31,7 +34,8 @@ pub struct TripProgress {
/// and [`update_user_location`](super::NavigationController::update_user_location).
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[cfg_attr(feature = "wasm-bindgen", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Serialize, Deserialize, Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub enum TripState {
/// The navigation controller is idle and there is no active trip.
Idle,
Expand Down Expand Up @@ -90,7 +94,8 @@ pub enum StepAdvanceStatus {
/// Controls filtering/post-processing of user course by the [`NavigationController`].
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[cfg_attr(feature = "wasm-bindgen", derive(Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Deserialize, Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(from_wasm_abi))]
pub enum CourseFiltering {
/// Snap the user's course to the current step's linestring using the next index in the step's geometry.
///
Expand All @@ -105,7 +110,8 @@ pub enum CourseFiltering {
/// and we should advance to the next step.
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[cfg_attr(feature = "wasm-bindgen", derive(Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Deserialize, Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(from_wasm_abi))]
pub enum StepAdvanceMode {
/// Never advances to the next step automatically;
/// requires calling [`NavigationController::advance_to_next_step`](super::NavigationController::advance_to_next_step).
Expand Down Expand Up @@ -136,8 +142,9 @@ pub enum StepAdvanceMode {

#[derive(Clone)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(feature = "wasm-bindgen", derive(Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Deserialize, Tsify))]
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "wasm-bindgen", tsify(from_wasm_abi))]
pub struct NavigationControllerConfig {
/// Configures when navigation advances to the next step in the route.
pub step_advance: StepAdvanceMode,
Expand Down
8 changes: 7 additions & 1 deletion common/ferrostar/src/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ use serde::{Deserialize, Serialize};
#[cfg(feature = "wasm-bindgen")]
use wasm_bindgen::{prelude::*, JsValue};

#[cfg(feature = "wasm-bindgen")]
use tsify::Tsify;

#[cfg(all(feature = "std", not(feature = "web-time")))]
use std::time::SystemTime;

Expand All @@ -64,7 +67,8 @@ use alloc::{
#[derive(Debug)]
#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[cfg_attr(feature = "uniffi", derive(uniffi::Error))]
#[cfg_attr(feature = "wasm-bindgen", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Serialize, Deserialize, Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub enum SimulationError {
#[cfg_attr(feature = "std", error("Failed to parse polyline: {error}."))]
/// Errors decoding the polyline string.
Expand All @@ -78,6 +82,8 @@ pub enum SimulationError {
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))]
pub struct LocationSimulationState {
pub current_location: UserLocation,
remaining_locations: Vec<GeographicCoordinate>,
Expand Down
24 changes: 14 additions & 10 deletions web/src/ferrostar-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import maplibregl, {
Map
} from "maplibre-gl";
import maplibreglStyles from "maplibre-gl/dist/maplibre-gl.css?inline";
import {NavigationController, RouteAdapter} from "@stadiamaps/ferrostar";
import {
NavigationController,
RouteAdapter,
TripState
} from "@stadiamaps/ferrostar";
import "./instructions-view";
import "./arrival-view";
import {SimulatedLocationProvider} from "./location";
Expand Down Expand Up @@ -47,9 +51,8 @@ export class FerrostarMap extends LitElement {
@property({ type: Object, attribute: false })
options: object = {};

// TODO: type
@state()
protected _tripState: any = null;
protected _tripState?: TripState;

// Configures the control on first load.
@property({ type: Function, attribute: false })
Expand Down Expand Up @@ -87,7 +90,7 @@ export class FerrostarMap extends LitElement {
geolocateControl: GeolocateControl | null = null;
navigationController: NavigationController | null = null;
simulatedLocationMarker: maplibregl.Marker | null = null;
lastSpokenInstructionText: string | null = null;
lastSpokenUtteranceId: string | null = null;

static styles = [
unsafeCSS(maplibreglStyles),
Expand Down Expand Up @@ -236,7 +239,7 @@ export class FerrostarMap extends LitElement {
return this.routeAdapter.parseResponse(responseData);
}

// TODO: type
// TODO: types
startNavigation(route: any, config: any) {
this.locationProvider.start();
if (this.onNavigationStart && this.map) this.onNavigationStart(this.map);
Expand Down Expand Up @@ -304,7 +307,7 @@ export class FerrostarMap extends LitElement {
this.routeAdapter = null;
this.navigationController?.free();
this.navigationController = null;
this._tripState = null;
this._tripState = undefined;
this.clearMap();
if (this.locationProvider) this.locationProvider.updateCallback = null;
if (this.onNavigationStop && this.map) this.onNavigationStop(this.map);
Expand All @@ -327,11 +330,12 @@ export class FerrostarMap extends LitElement {
});

// Speak the next instruction if voice guidance is enabled
if (this.useVoiceGuidance) {
if (this._tripState.Navigating?.spokenInstruction && this._tripState.Navigating?.spokenInstruction.text !== this.lastSpokenInstructionText) {
this.lastSpokenInstructionText = this._tripState.Navigating?.spokenInstruction.text;
const tripState = this._tripState;
if (this.useVoiceGuidance && tripState && typeof(tripState) === 'object') {
if ("Navigating" in tripState && tripState.Navigating?.spokenInstruction && tripState.Navigating?.spokenInstruction.utteranceId !== this.lastSpokenUtteranceId) {
this.lastSpokenUtteranceId = tripState.Navigating?.spokenInstruction.utteranceId;
window.speechSynthesis.cancel();
window.speechSynthesis.speak(new SpeechSynthesisUtterance(this._tripState.Navigating?.spokenInstruction.text));
window.speechSynthesis.speak(new SpeechSynthesisUtterance(tripState.Navigating?.spokenInstruction.text));
}
}
}
Expand Down
Loading