tauri_plugin_geolocation/
mobile.rs1use serde::{Serialize, de::DeserializeOwned};
6use tauri::{
7 AppHandle, Runtime,
8 ipc::{Channel, InvokeResponseBody},
9 plugin::{PluginApi, PluginHandle},
10};
11
12use crate::models::*;
13
14#[cfg(target_os = "android")]
15const PLUGIN_IDENTIFIER: &str = "app.tauri.geolocation";
16
17#[cfg(target_os = "ios")]
18tauri::ios_plugin_binding!(init_plugin_geolocation);
19
20pub fn init<R: Runtime, C: DeserializeOwned>(
22 _app: &AppHandle<R>,
23 api: PluginApi<R, C>,
24) -> crate::Result<Geolocation<R>> {
25 #[cfg(target_os = "android")]
26 let handle = api.register_android_plugin(PLUGIN_IDENTIFIER, "GeolocationPlugin")?;
27 #[cfg(target_os = "ios")]
28 let handle = api.register_ios_plugin(init_plugin_geolocation)?;
29 Ok(Geolocation(handle))
30}
31
32pub struct Geolocation<R: Runtime>(PluginHandle<R>);
34
35impl<R: Runtime> Geolocation<R> {
36 pub fn get_current_position(
38 &self,
39 options: Option<PositionOptions>,
40 ) -> crate::Result<Position> {
41 self.0
43 .run_mobile_plugin("getCurrentPosition", options.unwrap_or_default())
44 .map_err(Into::into)
45 }
46
47 pub fn watch_position<F: Fn(WatchEvent) + Send + Sync + 'static>(
49 &self,
50 options: PositionOptions,
51 callback: F,
52 ) -> crate::Result<u32> {
53 let channel = Channel::new(move |event| {
54 let payload = match event {
55 InvokeResponseBody::Json(payload) => serde_json::from_str::<WatchEvent>(&payload)
56 .unwrap_or_else(|error| {
57 WatchEvent::Error(format!(
58 "Couldn't deserialize watch event payload: `{error}`"
59 ))
60 }),
61 _ => WatchEvent::Error("Unexpected watch event payload.".to_string()),
62 };
63
64 callback(payload);
65
66 Ok(())
67 });
68 let id = channel.id();
69
70 self.watch_position_inner(options, channel)?;
71
72 Ok(id)
73 }
74
75 pub(crate) fn watch_position_inner(
76 &self,
77 options: PositionOptions,
78 channel: Channel,
79 ) -> crate::Result<()> {
80 self.0
81 .run_mobile_plugin("watchPosition", WatchPayload { options, channel })
82 .map_err(Into::into)
83 }
84
85 pub fn clear_watch(&self, channel_id: u32) -> crate::Result<()> {
87 self.0
88 .run_mobile_plugin("clearWatch", ClearWatchPayload { channel_id })
89 .map_err(Into::into)
90 }
91
92 pub fn check_permissions(&self) -> crate::Result<PermissionStatus> {
94 self.0
95 .run_mobile_plugin("checkPermissions", ())
96 .map_err(Into::into)
97 }
98
99 pub fn request_permissions(
101 &self,
102 permissions: Option<Vec<PermissionType>>,
103 ) -> crate::Result<PermissionStatus> {
104 self.0
105 .run_mobile_plugin(
106 "requestPermissions",
107 serde_json::json!({ "permissions": permissions }),
108 )
109 .map_err(Into::into)
110 }
111}
112
113#[derive(Serialize)]
114struct WatchPayload {
115 options: PositionOptions,
116 channel: Channel,
117}
118
119#[derive(Serialize)]
120#[serde(rename_all = "camelCase")]
121struct ClearWatchPayload {
122 channel_id: u32,
123}