pull/1889/merge
bradleat 2 weeks ago committed by GitHub
commit a89fdc05c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -93,7 +93,7 @@ export type PositionOptions = {
} }
export async function watchPosition( export async function watchPosition(
options: PositionOptions, options: PositionOptions & {requestUpdatesInBackground?: boolean},
cb: (location: Position | null, error?: string) => void cb: (location: Position | null, error?: string) => void
): Promise<number> { ): Promise<number> {
const channel = new Channel<Position | string>() const channel = new Channel<Position | string>()
@ -106,6 +106,7 @@ export async function watchPosition(
} }
await invoke('plugin:geolocation|watch_position', { await invoke('plugin:geolocation|watch_position', {
options, options,
requestUpdatesInBackground: options.requestUpdatesInBackground ?? false,
channel channel
}) })
return channel.id return channel.id
@ -130,9 +131,11 @@ export async function checkPermissions(): Promise<PermissionStatus> {
} }
export async function requestPermissions( export async function requestPermissions(
permissions: PermissionType[] | null permissions: PermissionType[] | null,
requestUpdatesInBackground: boolean = false
): Promise<PermissionStatus> { ): Promise<PermissionStatus> {
return await invoke('plugin:geolocation|request_permissions', { return await invoke('plugin:geolocation|request_permissions', {
permissions permissions,
requestUpdatesInBackground
}) })
} }

@ -14,6 +14,7 @@ class GetPositionArgs: Decodable {
class WatchPositionArgs: Decodable { class WatchPositionArgs: Decodable {
let options: GetPositionArgs let options: GetPositionArgs
let request_updates_in_background: Bool
let channel: Channel let channel: Channel
} }
@ -21,9 +22,20 @@ class ClearWatchArgs: Decodable {
let channelId: UInt32 let channelId: UInt32
} }
enum PermissionType: String, Decodable {
case location
case coarseLocation
}
class RequestPermissionsArgs: Decodable {
let permissions: [PermissionType]
let requestUpdatesInBackground: Bool
}
class GeolocationPlugin: Plugin, CLLocationManagerDelegate { class GeolocationPlugin: Plugin, CLLocationManagerDelegate {
private let locationManager = CLLocationManager() private let locationManager = CLLocationManager()
private var isUpdatingLocation: Bool = false private var isUpdatingLocation: Bool = false
private var backgroundUpdatesRequested: Bool = false
private var permissionRequests: [Invoke] = [] private var permissionRequests: [Invoke] = []
private var positionRequests: [Invoke] = [] private var positionRequests: [Invoke] = []
private var watcherChannels: [Channel] = [] private var watcherChannels: [Channel] = []
@ -61,6 +73,8 @@ class GeolocationPlugin: Plugin, CLLocationManagerDelegate {
@objc public func watchPosition(_ invoke: Invoke) throws { @objc public func watchPosition(_ invoke: Invoke) throws {
let args = try invoke.parseArgs(WatchPositionArgs.self) let args = try invoke.parseArgs(WatchPositionArgs.self)
self.backgroundUpdatesRequested = args.request_updates_in_background;
self.watcherChannels.append(args.channel) self.watcherChannels.append(args.channel)
DispatchQueue.main.async { DispatchQueue.main.async {
@ -70,12 +84,28 @@ class GeolocationPlugin: Plugin, CLLocationManagerDelegate {
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
} }
// TODO: Use the authorizationStatus instance property with locationManagerDidChangeAuthorization(_:) instead. // TODO: Use the authorizationStatus instance property with locationManagerDidChangeAuthorization(_:) instead.
if CLLocationManager.authorizationStatus() == .notDetermined { if CLLocationManager.authorizationStatus() == .notDetermined {
self.locationManager.requestWhenInUseAuthorization() if self.backgroundUpdatesRequested {
self.locationManager.requestAlwaysAuthorization()
} else {
self.locationManager.requestWhenInUseAuthorization()
}
} else { } else {
self.locationManager.startUpdatingLocation() if CLLocationManager.authorizationStatus() == .authorizedWhenInUse && self.backgroundUpdatesRequested {
self.isUpdatingLocation = true self.locationManager.requestAlwaysAuthorization()
} else {
self.locationManager.startUpdatingLocation()
self.isUpdatingLocation = true
// Enable background updates if enabled
if self.backgroundUpdatesRequested {
self.locationManager.allowsBackgroundLocationUpdates = true
self.locationManager.pausesLocationUpdatesAutomatically = false
self.locationManager.showsBackgroundLocationIndicator = true
}
}
} }
} }
@ -125,9 +155,19 @@ class GeolocationPlugin: Plugin, CLLocationManagerDelegate {
// TODO: Use the authorizationStatus instance property with locationManagerDidChangeAuthorization(_:) instead. // TODO: Use the authorizationStatus instance property with locationManagerDidChangeAuthorization(_:) instead.
if CLLocationManager.authorizationStatus() == .notDetermined { if CLLocationManager.authorizationStatus() == .notDetermined {
self.permissionRequests.append(invoke) self.permissionRequests.append(invoke)
do {
DispatchQueue.main.async { let args = try invoke.parseArgs(RequestPermissionsArgs.self)
self.locationManager.requestWhenInUseAuthorization()
DispatchQueue.main.async {
self.locationManager.requestWhenInUseAuthorization()
if args.requestUpdatesInBackground {
// Request background permission if requested
self.locationManager.requestAlwaysAuthorization()
self.backgroundUpdatesRequested = true
}
}
} catch {
invoke.reject(error.localizedDescription)
} }
} else { } else {
checkPermissions(invoke) checkPermissions(invoke)
@ -224,6 +264,11 @@ class GeolocationPlugin: Plugin, CLLocationManagerDelegate {
private func stopUpdating() { private func stopUpdating() {
self.locationManager.stopUpdatingLocation() self.locationManager.stopUpdatingLocation()
self.isUpdatingLocation = false self.isUpdatingLocation = false
if self.backgroundUpdatesRequested {
self.locationManager.allowsBackgroundLocationUpdates = false
self.locationManager.pausesLocationUpdatesAutomatically = true
self.locationManager.showsBackgroundLocationIndicator = false
}
} }
private func convertLocation(_ location: CLLocation) -> JsonObject { private func convertLocation(_ location: CLLocation) -> JsonObject {

@ -0,0 +1,3 @@
[default]
description = "Default permissions for the plugin"
permissions = ["allow-request-permissions", "allow-check-permissions", "allow-clear-watch", "allow-watch-position", "allow-get-current-position"]

@ -18,9 +18,10 @@ pub(crate) async fn get_current_position<R: Runtime>(
pub(crate) async fn watch_position<R: Runtime>( pub(crate) async fn watch_position<R: Runtime>(
app: AppHandle<R>, app: AppHandle<R>,
options: PositionOptions, options: PositionOptions,
request_updates_in_background: bool,
channel: Channel, channel: Channel,
) -> Result<()> { ) -> Result<()> {
app.geolocation().watch_position_inner(options, channel) app.geolocation().watch_position_inner(options, channel, request_updates_in_background)
} }
#[command] #[command]
@ -37,6 +38,7 @@ pub(crate) async fn check_permissions<R: Runtime>(app: AppHandle<R>) -> Result<P
pub(crate) async fn request_permissions<R: Runtime>( pub(crate) async fn request_permissions<R: Runtime>(
app: AppHandle<R>, app: AppHandle<R>,
permissions: Option<Vec<PermissionType>>, permissions: Option<Vec<PermissionType>>,
request_updates_in_background: bool,
) -> Result<PermissionStatus> { ) -> Result<PermissionStatus> {
app.geolocation().request_permissions(permissions) app.geolocation().request_permissions(permissions, request_updates_in_background)
} }

@ -32,6 +32,7 @@ impl<R: Runtime> Geolocation<R> {
pub fn watch_position<F: Fn(WatchEvent) + Send + Sync + 'static>( pub fn watch_position<F: Fn(WatchEvent) + Send + Sync + 'static>(
&self, &self,
options: PositionOptions, options: PositionOptions,
request_updates_in_background: bool,
callback: F, callback: F,
) -> crate::Result<u32> { ) -> crate::Result<u32> {
let channel = Channel::new(move |event| { let channel = Channel::new(move |event| {
@ -51,7 +52,7 @@ impl<R: Runtime> Geolocation<R> {
}); });
let id = channel.id(); let id = channel.id();
self.watch_position_inner(options, channel)?; self.watch_position_inner(options, request_updates_in_background, channel)?;
Ok(id) Ok(id)
} }
@ -59,6 +60,7 @@ impl<R: Runtime> Geolocation<R> {
pub(crate) fn watch_position_inner( pub(crate) fn watch_position_inner(
&self, &self,
_options: PositionOptions, _options: PositionOptions,
_request_updates_in_background: bool,
_callback_channel: Channel, _callback_channel: Channel,
) -> crate::Result<()> { ) -> crate::Result<()> {
Ok(()) Ok(())
@ -75,6 +77,7 @@ impl<R: Runtime> Geolocation<R> {
pub fn request_permissions( pub fn request_permissions(
&self, &self,
_permissions: Option<Vec<PermissionType>>, _permissions: Option<Vec<PermissionType>>,
_request_updates_in_background: bool,
) -> crate::Result<PermissionStatus> { ) -> crate::Result<PermissionStatus> {
Ok(PermissionStatus::default()) Ok(PermissionStatus::default())
} }

@ -47,6 +47,7 @@ impl<R: Runtime> Geolocation<R> {
pub fn watch_position<F: Fn(WatchEvent) + Send + Sync + 'static>( pub fn watch_position<F: Fn(WatchEvent) + Send + Sync + 'static>(
&self, &self,
options: PositionOptions, options: PositionOptions,
request_updates_in_background: bool,
callback: F, callback: F,
) -> crate::Result<u32> { ) -> crate::Result<u32> {
let channel = Channel::new(move |event| { let channel = Channel::new(move |event| {
@ -66,7 +67,7 @@ impl<R: Runtime> Geolocation<R> {
}); });
let id = channel.id(); let id = channel.id();
self.watch_position_inner(options, channel)?; self.watch_position_inner(options, request_updates_in_background, channel)?;
Ok(id) Ok(id)
} }
@ -74,10 +75,18 @@ impl<R: Runtime> Geolocation<R> {
pub(crate) fn watch_position_inner( pub(crate) fn watch_position_inner(
&self, &self,
options: PositionOptions, options: PositionOptions,
request_updates_in_background: bool,
channel: Channel, channel: Channel,
) -> crate::Result<()> { ) -> crate::Result<()> {
self.0 self.0
.run_mobile_plugin("watchPosition", WatchPayload { options, channel }) .run_mobile_plugin(
"watchPosition",
WatchPayload {
options,
channel,
request_updates_in_background,
},
)
.map_err(Into::into) .map_err(Into::into)
} }
@ -96,11 +105,15 @@ impl<R: Runtime> Geolocation<R> {
pub fn request_permissions( pub fn request_permissions(
&self, &self,
permissions: Option<Vec<PermissionType>>, permissions: Option<Vec<PermissionType>>,
request_updates_in_background: bool,
) -> crate::Result<PermissionStatus> { ) -> crate::Result<PermissionStatus> {
self.0 self.0
.run_mobile_plugin( .run_mobile_plugin(
"requestPermissions", "requestPermissions",
serde_json::json!({ "permissions": permissions }), serde_json::json!({
"permissions": permissions,
"requestUpdatesInBackground": request_updates_in_background,
}),
) )
.map_err(Into::into) .map_err(Into::into)
} }

Loading…
Cancel
Save