dioxus_std/geolocation/
core.rs

1//! Provides access to the target device's geolocation system.
2
3use super::platform;
4use core::fmt;
5use dioxus::prelude::Coroutine;
6use std::sync::Arc;
7
8/// Describes a position in the world.
9#[derive(Debug, Clone)]
10pub struct Geocoordinates {
11    pub latitude: f64,
12    pub longitude: f64,
13}
14
15/// To conserve battery, some devices allow setting a desired accuracy based on your use-case.
16#[derive(Debug)]
17pub enum PowerMode {
18    /// Will generally enable the on-board GPS for precise coordinates.
19    High,
20    /// Will generally use cell towers or WiFi beacons to determine the device's location.
21    Low,
22}
23
24/// Represents a geolocation event.
25#[derive(Debug)]
26pub enum Event {
27    /// The status of the device has changed.
28    StatusChanged(Status),
29    /// New coordinates are available.
30    NewGeocoordinates(Geocoordinates),
31}
32
33/// Describes whether your application has access or not.
34#[derive(Debug)]
35pub enum Access {
36    Allowed,
37    Denied,
38    /// This is returned when the access level was not able to be determined.
39    Unspecified,
40}
41
42/// Describes the geolocation device's status.
43#[derive(Debug, PartialEq)]
44pub enum Status {
45    /// Location service or device is ready and has geo data.
46    Ready,
47    /// Location service or device is disabled.
48    Disabled,
49    /// Location service or device is not available.
50    NotAvailable,
51    /// Location service or device is initializing.
52    Initializing,
53    /// Unable to determine location service or device status. (This shouldn't happen)
54    Unknown,
55}
56
57/// Represents the geolocation abstraction.
58pub struct Geolocator {
59    device_geolocator: platform::Geolocator,
60}
61
62impl Geolocator {
63    /// Create a new geolocator.
64    pub fn new(power_mode: PowerMode) -> Result<Self, Error> {
65        let mut device_geolocator = platform::Geolocator::new()?;
66        platform::set_power_mode(&mut device_geolocator, power_mode)?;
67
68        Ok(Self { device_geolocator })
69    }
70
71    /// Get the latest coordinates from the device.
72    pub async fn get_coordinates(&self) -> Result<Geocoordinates, Error> {
73        platform::get_coordinates(&self.device_geolocator).await
74    }
75
76    /// Subscribe a mpsc channel to the events.
77    pub fn listen(&self, listener: Coroutine<Event>) -> Result<(), Error> {
78        let tx = listener.tx();
79        platform::listen(
80            &self.device_geolocator,
81            Arc::new(move |event: Event| {
82                tx.unbounded_send(event).ok();
83            }),
84        )
85    }
86}
87
88/// Describes errors that may occur when utilizing the geolocation abstraction.
89#[derive(Debug, Clone)]
90pub enum Error {
91    NotInitialized,
92    AccessDenied,
93    Poisoned,
94    DeviceError(String),
95}
96
97impl std::error::Error for Error {}
98impl fmt::Display for Error {
99    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100        match self {
101            Error::NotInitialized => write!(f, "not initialized"),
102            Error::AccessDenied => {
103                write!(f, "access denied (access may have been revoked during use)")
104            }
105            Error::Poisoned => write!(f, "the internal read/write lock has been poisioned"),
106            Error::DeviceError(e) => write!(f, "a device error has occurred: {}", e),
107        }
108    }
109}