Skip to content

Commit

Permalink
Initial draft of adding TypeScript types (#181)
Browse files Browse the repository at this point in the history
* Initial draft of adding TypeScript types

* Revert "Initial draft of adding TypeScript types"

This reverts commit f983a71.

* Use Tsify to generate TypeScript type declarations

* Fix Rust core non-wasm target builds

* Cargo update

* Merge fallout

* A few more steps in the right direction!

* Feature gate

* rustfmt

* Minor revisions

---------

Co-authored-by: Ian Wagner <ian.wagner@stadiamaps.com>
  • Loading branch information
CatMe0w and ianthetechie authored Oct 8, 2024
1 parent eadf4bd commit 6b1d3cb
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 78 deletions.
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
22 changes: 13 additions & 9 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 | null = null;

// 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 @@ -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 != null && 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

0 comments on commit 6b1d3cb

Please sign in to comment.