refactor(geolocation): simplify API, defer permission checks (#1773)

This commit is contained in:
Lucas Fernandes Nogueira
2024-09-16 11:01:13 -03:00
committed by GitHub
parent fd75401aee
commit 60765694f5
28 changed files with 454 additions and 13969 deletions
@@ -60,18 +60,8 @@ private const val ALIAS_COARSE_LOCATION: String = "coarseLocation"
]
)
class GeolocationPlugin(private val activity: Activity): Plugin(activity) {
private lateinit var implementation: Geolocation// = Geolocation(activity.applicationContext)
private var watchers = hashMapOf<Long, Invoke>()
// If multiple permissions get requested in quick succession not all callbacks will be fired,
// So we'll store all requests ourselves instead of using the callback argument.
private var positionRequests = mutableListOf<Invoke>()
private var watchRequests = mutableListOf<Invoke>()
// If getCurrentPosition or watchPosition are called before a prior call is done requesting permission,
// the callback will be called with denied for the prior call(s) so we keep track of them to make sure
// to only run the logic on the last request.
// TODO: Find a better solution after switching to explicit requestPermissions call - likely needs changes in Tauri
private var ongoingPermissionRequests = 0;
private lateinit var implementation: Geolocation
private var watchers = hashMapOf<Long, Pair<Invoke, WatchArgs>>()
override fun load(webView: WebView) {
super.load(webView)
@@ -86,8 +76,9 @@ class GeolocationPlugin(private val activity: Activity): Plugin(activity) {
override fun onResume() {
super.onResume()
for (watcher in watchers.values) {
startWatch(watcher)
// resume watchers
for ((watcher, args) in watchers.values) {
startWatch(watcher, args)
}
}
@@ -112,83 +103,39 @@ class GeolocationPlugin(private val activity: Activity): Plugin(activity) {
@Command
fun getCurrentPosition(invoke: Invoke) {
val args = invoke.parseArgs(PositionOptions::class.java)
val alias = getAlias(args.enableHighAccuracy)
if (getPermissionState(alias) != PermissionState.GRANTED) {
Logger.error("NOT GRANTED");
this.positionRequests.add(invoke)
this.ongoingPermissionRequests += 1
requestPermissionForAlias(alias, invoke, "positionPermissionCallback")
val location = implementation.getLastLocation(args.maximumAge)
if (location != null) {
invoke.resolve(convertLocation(location))
} else {
Logger.error("GRANTED");
getPosition(invoke, args)
implementation.sendLocation(args.enableHighAccuracy,
{ loc -> invoke.resolve(convertLocation(loc)) },
{ error -> invoke.reject(error) })
}
}
@PermissionCallback
private fun positionPermissionCallback(invoke: Invoke) {
Logger.error("positionPermissionCallback - ongoingRequests: " + this.ongoingPermissionRequests.toString())
this.ongoingPermissionRequests -= 1
if (this.ongoingPermissionRequests > 0) {
return
}
val pRequests = this.positionRequests.toTypedArray()
val wRequests = this.watchRequests.toTypedArray()
this.positionRequests.clear()
this.watchRequests.clear()
// TODO: capacitor only checks for coarse here
val permissionGranted = getPermissionState(ALIAS_COARSE_LOCATION) == PermissionState.GRANTED;
Logger.error("positionPermissionCallback - permissionGranted: $permissionGranted");
for (inv in pRequests) {
if (permissionGranted) {
val args = inv.parseArgs(PositionOptions::class.java)
implementation.sendLocation(args.enableHighAccuracy,
{ location -> inv.resolve(convertLocation(location)) },
{ error -> inv.reject(error) })
} else {
inv.reject("Location permission was denied.")
}
}
for (inv in wRequests) {
if (permissionGranted) {
startWatch(invoke)
} else {
inv.reject("Location permission was denied.")
}
}
val permissionsResultJSON = JSObject()
permissionsResultJSON.put("location", getPermissionState(ALIAS_LOCATION))
permissionsResultJSON.put("coarseLocation", getPermissionState(ALIAS_COARSE_LOCATION))
invoke.resolve(permissionsResultJSON)
}
@Command
fun watchPosition(invoke: Invoke) {
val args = invoke.parseArgs(WatchArgs::class.java)
val alias = getAlias(args.options.enableHighAccuracy)
if (getPermissionState(alias) != PermissionState.GRANTED) {
this.watchRequests.add(invoke)
this.ongoingPermissionRequests += 1
requestPermissionForAlias(alias, invoke, "positionPermissionCallback")
} else {
startWatch(invoke)
}
startWatch(invoke, args)
}
private fun startWatch(invoke: Invoke) {
val args = invoke.parseArgs(WatchArgs::class.java)
private fun startWatch(invoke: Invoke, args: WatchArgs) {
implementation.requestLocationUpdates(
args.options.enableHighAccuracy,
args.options.timeout,
{ location -> args.channel.send(convertLocation(location)) },
{ error -> args.channel.sendObject(error) })
watchers[args.channel.id] = invoke
watchers[args.channel.id] = Pair(invoke, args)
}
@Command
@@ -204,19 +151,6 @@ class GeolocationPlugin(private val activity: Activity): Plugin(activity) {
invoke.resolve()
}
private fun getPosition(invoke: Invoke, options: PositionOptions) {
val location = implementation.getLastLocation(options.maximumAge)
if (location != null) {
Logger.error("getPosition location non-null")
invoke.resolve(convertLocation(location))
} else {
Logger.error("getPosition location null")
implementation.sendLocation(options.enableHighAccuracy,
{ loc -> invoke.resolve(convertLocation(loc)) },
{ error -> invoke.reject(error) })
}
}
private fun convertLocation(location: Location): JSObject {
val ret = JSObject()
val coords = JSObject()
@@ -235,14 +169,4 @@ class GeolocationPlugin(private val activity: Activity): Plugin(activity) {
return ret
}
private fun getAlias(enableHighAccuracy: Boolean): String {
var alias = ALIAS_LOCATION;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (!enableHighAccuracy) {
alias = ALIAS_COARSE_LOCATION;
}
}
return alias
}
}