dioxus_leaflet/
interop.rs

1use dioxus::prelude::*;
2use dioxus_use_js::{JsError, SerdeJsonValue};
3use std::error::Error;
4
5use crate::{LatLng, MapOptions, MapPosition, MarkerIcon, PathOptions, PopupOptions, types::Id};
6
7pub const DL_JS: Asset = asset!("/assets/dioxus_leaflet.js");
8
9mod js_api {
10    use dioxus::prelude::*;
11    use dioxus_use_js::use_js;
12
13    use_js!("js_utils/src/map.ts", "assets/dioxus_leaflet.js"::{update_map, delete_map, on_map_click, on_map_move});
14    use_js!("js_utils/src/marker.ts", "assets/dioxus_leaflet.js"::{update_marker, delete_marker});
15    use_js!("js_utils/src/polygon.ts", "assets/dioxus_leaflet.js"::{update_polygon, delete_polygon});
16    use_js!("js_utils/src/popup.ts", "assets/dioxus_leaflet.js"::{update_popup});
17}
18
19fn js_to_eval(err: JsError) -> Box<dyn Error + Send + Sync> {
20    match err {
21        JsError::Eval { error, .. } => error.into(),
22        JsError::Threw { func, .. } => Box::<dyn Error + Send + Sync>::from(func),
23    }
24}
25
26pub async fn update_map<'a>(
27    id: &Id,
28    initial_position: &MapPosition,
29    options: &MapOptions,
30) -> Result<(), Box<dyn Error + Send + Sync>> {
31    js_api::update_map(id, initial_position, options)
32        .await
33        .map_err(js_to_eval)
34}
35
36pub async fn delete_map<'a>(id: &Id) -> Result<(), Box<dyn Error + Send + Sync>> {
37    js_api::delete_map(id).await.map_err(js_to_eval)
38}
39
40pub async fn on_map_click(map_id: &Id, callback: EventHandler<LatLng>) -> Result<(), Box<dyn Error + Send + Sync>> {
41    let mapper_cb = Callback::new(move |coords: Vec<f64>| async move {
42        callback.call(LatLng::new(coords[0], coords[1]));
43        Result::<(), SerdeJsonValue>::Ok(())
44    });
45    js_api::on_map_click(map_id, mapper_cb).await.map_err(js_to_eval)
46}
47
48pub async fn on_map_move(map_id: &Id, callback: EventHandler<MapPosition>) -> Result<(), Box<dyn Error + Send + Sync>> {
49    let mapper_cb = Callback::new(move |data: Vec<f64>| async move {
50        let pos = MapPosition { coordinates: LatLng::new(data[0], data[1]), zoom: data[2] };
51        callback.call(pos);
52        Result::<(), SerdeJsonValue>::Ok(())
53    });
54    js_api::on_map_move(map_id, mapper_cb).await.map_err(js_to_eval)
55}
56
57pub async fn update_marker(
58    marker_id: &Id,
59    coordinate: &LatLng,
60    icon: &Option<MarkerIcon>,
61) -> Result<(), Box<dyn Error + Send + Sync>> {
62    js_api::update_marker(
63        marker_id.parent().unwrap(),
64        marker_id.id(),
65        coordinate,
66        icon,
67    )
68    .await
69    .map_err(js_to_eval)
70}
71
72pub async fn delete_marker(marker_id: &Id) -> Result<(), Box<dyn Error + Send + Sync>> {
73    js_api::delete_marker(marker_id.parent().unwrap(), marker_id.id())
74        .await
75        .map_err(js_to_eval)
76}
77
78pub async fn update_polygon(
79    polygon_id: &Id,
80    coordinates: &Vec<Vec<Vec<LatLng>>>,
81    options: &PathOptions,
82) -> Result<(), Box<dyn Error + Send + Sync>> {
83    js_api::update_polygon(
84        polygon_id.parent().unwrap(),
85        polygon_id.id(),
86        coordinates,
87        options,
88    )
89    .await
90    .map_err(js_to_eval)
91}
92
93pub async fn delete_polygon(polygon_id: &Id) -> Result<(), Box<dyn Error + Send + Sync>> {
94    js_api::delete_polygon(polygon_id.parent().unwrap(), polygon_id.id())
95        .await
96        .map_err(js_to_eval)
97}
98
99pub async fn update_popup(
100    popup_id: &Id,
101    options: &PopupOptions,
102) -> Result<(), Box<dyn Error + Send + Sync>> {
103    let marker_id = popup_id.parent().unwrap();
104    js_api::update_popup(marker_id, popup_id, options)
105        .await
106        .map_err(js_to_eval)
107}