// Copyright 2019-2023 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use serde::{de::DeserializeOwned, Serialize}; use tauri::{ ipc::{Channel, InvokeBody}, plugin::{PluginApi, PluginHandle}, AppHandle, Runtime, }; use crate::models::*; #[cfg(target_os = "android")] const PLUGIN_IDENTIFIER: &str = "app.tauri.geolocation"; #[cfg(target_os = "ios")] tauri::ios_plugin_binding!(init_plugin_geolocation); // initializes the Kotlin or Swift plugin classes pub fn init( _app: &AppHandle, api: PluginApi, ) -> crate::Result> { #[cfg(target_os = "android")] let handle = api.register_android_plugin(PLUGIN_IDENTIFIER, "GeolocationPlugin")?; #[cfg(target_os = "ios")] let handle = api.register_ios_plugin(init_plugin_geolocation)?; Ok(Geolocation(handle)) } /// Access to the geolocation APIs. pub struct Geolocation(PluginHandle); impl Geolocation { pub fn get_current_position( &self, options: Option, ) -> crate::Result { // TODO: We may have to send over None if that's better on Android self.0 .run_mobile_plugin("getCurrentPosition", options.unwrap_or_default()) .map_err(Into::into) } /// Register a position watcher. This method returns an id to use in `clear_watch`. pub fn watch_position( &self, options: PositionOptions, callback: F, ) -> crate::Result { let channel = Channel::new(move |event| { let payload = match event { InvokeBody::Json(payload) => serde_json::from_value::(dbg!(payload)) .unwrap_or_else(|error| { WatchEvent::Error(format!( "Couldn't deserialize watch event payload: `{error}`" )) }), _ => WatchEvent::Error("Unexpected watch event payload.".to_string()), }; callback(payload); Ok(()) }); let id = channel.id(); self.watch_position_inner(options, channel)?; Ok(id) } pub(crate) fn watch_position_inner( &self, options: PositionOptions, channel: Channel, ) -> crate::Result<()> { self.0 .run_mobile_plugin("watchPosition", WatchPayload { options, channel }) .map_err(Into::into) } pub fn clear_watch(&self, channel_id: u32) -> crate::Result<()> { self.0 .run_mobile_plugin("clearWatch", ClearWatchPayload { channel_id }) .map_err(Into::into) } pub fn check_permissions(&self) -> crate::Result { self.0 .run_mobile_plugin("checkPermissions", ()) .map_err(Into::into) } pub fn request_permissions( &self, permissions: Option>, ) -> crate::Result { self.0 .run_mobile_plugin("requestPermissions", permissions) .map_err(Into::into) } } #[derive(Serialize)] struct WatchPayload { options: PositionOptions, channel: Channel, } #[derive(Serialize)] #[serde(rename_all = "camelCase")] struct ClearWatchPayload { channel_id: u32, }