dioxus_std/geolocation/platform/
windows.rs1use std::sync::Arc;
2
3use windows::{
4 Devices::Geolocation::{
5 BasicGeoposition, GeolocationAccessStatus, Geolocator as WindowsGeolocator,
6 PositionAccuracy, PositionChangedEventArgs, PositionStatus, StatusChangedEventArgs,
7 },
8 Foundation::TypedEventHandler,
9};
10
11use crate::geolocation::core::{Error, Event, Geocoordinates, PowerMode, Status};
12
13pub struct Geolocator {
15 device_geolocator: WindowsGeolocator,
16}
17
18impl Geolocator {
19 pub fn new() -> Result<Self, Error> {
21 let access_status = match WindowsGeolocator::RequestAccessAsync() {
23 Ok(v) => v,
24 Err(e) => return Err(Error::DeviceError(e.to_string())),
25 };
26
27 let access_status = match access_status.get() {
28 Ok(v) => v,
29 Err(e) => return Err(Error::DeviceError(e.to_string())),
30 };
31
32 if access_status != GeolocationAccessStatus::Allowed {
33 return Err(Error::AccessDenied);
34 }
35
36 let device_geolocator =
38 WindowsGeolocator::new().map_err(|e| Error::DeviceError(e.to_string()))?;
39
40 Ok(Self { device_geolocator })
41 }
42}
43
44pub async fn get_coordinates(geolocator: &Geolocator) -> Result<Geocoordinates, Error> {
45 let location = geolocator.device_geolocator.GetGeopositionAsync();
46
47 let location = match location {
48 Ok(v) => v,
49 Err(e) => return Err(Error::DeviceError(e.to_string())),
50 };
51
52 let location = match location.get() {
53 Ok(v) => v,
54 Err(e) => return Err(Error::DeviceError(e.to_string())),
55 };
56
57 let location_coordinate = match location.Coordinate() {
58 Ok(v) => v,
59 Err(e) => return Err(Error::DeviceError(e.to_string())),
60 };
61
62 let location_point = match location_coordinate.Point() {
63 Ok(v) => v,
64 Err(e) => return Err(Error::DeviceError(e.to_string())),
65 };
66
67 let position = match location_point.Position() {
68 Ok(v) => v,
69 Err(e) => return Err(Error::DeviceError(e.to_string())),
70 };
71
72 Ok(position.into())
73}
74
75pub fn listen(
77 geolocator: &Geolocator,
78 callback: Arc<dyn Fn(Event) + Send + Sync>,
79) -> Result<(), Error> {
80 let callback1 = callback.clone();
81 let callback2 = callback.clone();
82
83 geolocator
85 .device_geolocator
86 .StatusChanged(&TypedEventHandler::new(
87 move |_geolocator: &Option<WindowsGeolocator>,
88 event_args: &Option<StatusChangedEventArgs>| {
89 if let Some(status) = event_args {
90 let status = status.Status()?;
92
93 (callback1)(Event::StatusChanged(status.into()))
95 }
96 Ok(())
97 },
98 ))
99 .map_err(|e| Error::DeviceError(e.to_string()))?;
100
101 geolocator
103 .device_geolocator
104 .PositionChanged(&TypedEventHandler::new(
105 move |_geolocator: &Option<WindowsGeolocator>,
106 event_args: &Option<PositionChangedEventArgs>| {
107 if let Some(position) = event_args {
108 let position = position.Position()?.Coordinate()?.Point()?.Position()?;
110
111 (callback2)(Event::NewGeocoordinates(position.into()))
113 }
114 Ok(())
115 },
116 ))
117 .map_err(|e| Error::DeviceError(e.to_string()))?;
118
119 Ok(())
120}
121
122pub fn set_power_mode(geolocator: &mut Geolocator, power_mode: PowerMode) -> Result<(), Error> {
124 match power_mode {
125 PowerMode::High => geolocator
126 .device_geolocator
127 .SetDesiredAccuracy(PositionAccuracy::High)
128 .map_err(|e| Error::DeviceError(e.to_string()))?,
129 PowerMode::Low => geolocator
130 .device_geolocator
131 .SetDesiredAccuracy(PositionAccuracy::Default)
132 .map_err(|e| Error::DeviceError(e.to_string()))?,
133 };
134
135 Ok(())
136}
137
138impl From<PositionStatus> for Status {
139 fn from(value: PositionStatus) -> Self {
140 match value.0 {
141 0 => Status::Ready,
142 1 => Status::Initializing,
143 3 => Status::Disabled,
144 5 => Status::NotAvailable,
145 _ => Status::Unknown,
146 }
147 }
148}
149
150impl From<BasicGeoposition> for Geocoordinates {
151 fn from(position: BasicGeoposition) -> Self {
152 Geocoordinates {
153 latitude: position.Latitude,
154 longitude: position.Longitude,
155 }
156 }
157}