@elizaos/capacitor-location 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ElizaosCapacitorLocation.podspec +17 -0
- package/android/build.gradle +45 -0
- package/android/src/main/AndroidManifest.xml +5 -0
- package/android/src/main/java/ai/eliza/plugins/location/LocationPlugin.kt +346 -0
- package/dist/esm/definitions.d.ts +133 -0
- package/dist/esm/definitions.d.ts.map +1 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +20 -0
- package/dist/esm/web.d.ts.map +1 -0
- package/dist/esm/web.js +133 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +148 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +151 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/LocationPlugin/LocationPlugin.swift +391 -0
- package/package.json +83 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'ElizaosCapacitorLocation'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license'] || { :type => 'MIT' }
|
|
10
|
+
s.homepage = 'https://elizaos.ai'
|
|
11
|
+
s.authors = { 'elizaOS' => 'dev@elizaos.ai' }
|
|
12
|
+
s.source = { :git => 'https://github.com/elizaOS/eliza.git', :tag => s.version.to_s }
|
|
13
|
+
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
+
s.ios.deployment_target = '13.0'
|
|
15
|
+
s.dependency 'Capacitor'
|
|
16
|
+
s.swift_version = '5.1'
|
|
17
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
ext {
|
|
2
|
+
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
|
|
4
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.5'
|
|
5
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.5.1'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
apply plugin: 'com.android.library'
|
|
9
|
+
android {
|
|
10
|
+
namespace = "ai.eliza.plugins.location"
|
|
11
|
+
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 34
|
|
12
|
+
defaultConfig {
|
|
13
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
|
14
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 34
|
|
15
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
16
|
+
}
|
|
17
|
+
buildTypes {
|
|
18
|
+
release {
|
|
19
|
+
minifyEnabled false
|
|
20
|
+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
compileOptions {
|
|
24
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
25
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
repositories {
|
|
30
|
+
google()
|
|
31
|
+
maven {
|
|
32
|
+
url = uri(rootProject.ext.mavenCentralMirrorUrl)
|
|
33
|
+
}
|
|
34
|
+
mavenCentral()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
dependencies {
|
|
38
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
39
|
+
implementation project(':capacitor-android')
|
|
40
|
+
implementation 'com.google.android.gms:play-services-location:21.3.0'
|
|
41
|
+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
42
|
+
testImplementation "junit:junit:$junitVersion"
|
|
43
|
+
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
44
|
+
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
45
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
4
|
+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
5
|
+
</manifest>
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
package ai.eliza.plugins.location
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.content.pm.PackageManager
|
|
5
|
+
import android.location.Location
|
|
6
|
+
import android.os.Build
|
|
7
|
+
import android.os.Looper
|
|
8
|
+
import androidx.core.content.ContextCompat
|
|
9
|
+
import com.getcapacitor.JSObject
|
|
10
|
+
import com.getcapacitor.Plugin
|
|
11
|
+
import com.getcapacitor.PluginCall
|
|
12
|
+
import com.getcapacitor.PluginMethod
|
|
13
|
+
import com.getcapacitor.annotation.CapacitorPlugin
|
|
14
|
+
import com.getcapacitor.annotation.Permission
|
|
15
|
+
import com.getcapacitor.annotation.PermissionCallback
|
|
16
|
+
import com.google.android.gms.location.*
|
|
17
|
+
import java.util.UUID
|
|
18
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* ElizaLocation Capacitor Plugin
|
|
22
|
+
*
|
|
23
|
+
* Provides location services using Google Play Services FusedLocationProviderClient.
|
|
24
|
+
* Supports one-shot position, continuous watching, maxAge caching, and background location.
|
|
25
|
+
*/
|
|
26
|
+
@CapacitorPlugin(
|
|
27
|
+
name = "ElizaLocation",
|
|
28
|
+
permissions = [
|
|
29
|
+
Permission(alias = "location", strings = [
|
|
30
|
+
Manifest.permission.ACCESS_FINE_LOCATION,
|
|
31
|
+
Manifest.permission.ACCESS_COARSE_LOCATION
|
|
32
|
+
]),
|
|
33
|
+
Permission(alias = "background", strings = [
|
|
34
|
+
Manifest.permission.ACCESS_BACKGROUND_LOCATION
|
|
35
|
+
])
|
|
36
|
+
]
|
|
37
|
+
)
|
|
38
|
+
class LocationPlugin : Plugin() {
|
|
39
|
+
|
|
40
|
+
private var fusedLocationClient: FusedLocationProviderClient? = null
|
|
41
|
+
private val watches = ConcurrentHashMap<String, LocationCallback>()
|
|
42
|
+
private var pendingCall: PluginCall? = null
|
|
43
|
+
private var pendingAction: String? = null
|
|
44
|
+
|
|
45
|
+
// Cache the last known location for maxAge support
|
|
46
|
+
private var lastKnownLocation: Location? = null
|
|
47
|
+
|
|
48
|
+
override fun load() {
|
|
49
|
+
super.load()
|
|
50
|
+
fusedLocationClient = LocationServices.getFusedLocationProviderClient(activity)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ── getCurrentPosition ──────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
@PluginMethod
|
|
56
|
+
fun getCurrentPosition(call: PluginCall) {
|
|
57
|
+
if (!hasRequiredPermissions()) {
|
|
58
|
+
pendingCall = call
|
|
59
|
+
pendingAction = "getCurrentPosition"
|
|
60
|
+
requestAllPermissions(call, "handlePermissionResult")
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
getCurrentPositionInternal(call)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private fun getCurrentPositionInternal(call: PluginCall) {
|
|
67
|
+
val accuracy = call.getString("accuracy") ?: "high"
|
|
68
|
+
val timeout = call.getDouble("timeout") ?: 10000.0
|
|
69
|
+
val maxAge = call.getDouble("maxAge") ?: 0.0
|
|
70
|
+
val priority = mapAccuracyToPriority(accuracy)
|
|
71
|
+
|
|
72
|
+
// maxAge > 0: try returning cached location if fresh enough (mirrors classic bestLastKnown)
|
|
73
|
+
if (maxAge > 0) {
|
|
74
|
+
try {
|
|
75
|
+
fusedLocationClient?.lastLocation?.addOnSuccessListener { cached ->
|
|
76
|
+
if (cached != null) {
|
|
77
|
+
val age = System.currentTimeMillis() - cached.time
|
|
78
|
+
if (age <= maxAge.toLong()) {
|
|
79
|
+
lastKnownLocation = cached
|
|
80
|
+
call.resolve(buildLocationResult(cached, cached = true))
|
|
81
|
+
return@addOnSuccessListener
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Cache miss — fall through to a fresh fix
|
|
85
|
+
requestFreshLocation(call, priority, timeout, maxAge)
|
|
86
|
+
}?.addOnFailureListener {
|
|
87
|
+
requestFreshLocation(call, priority, timeout, maxAge)
|
|
88
|
+
}
|
|
89
|
+
return
|
|
90
|
+
} catch (_: SecurityException) {
|
|
91
|
+
// Permission lost between check and call — fall through
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
requestFreshLocation(call, priority, timeout, maxAge)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Request a fresh location using CurrentLocationRequest. */
|
|
99
|
+
private fun requestFreshLocation(call: PluginCall, priority: Int, timeout: Double, maxAge: Double) {
|
|
100
|
+
val request = CurrentLocationRequest.Builder()
|
|
101
|
+
.setPriority(priority)
|
|
102
|
+
.setMaxUpdateAgeMillis(maxAge.toLong())
|
|
103
|
+
.setDurationMillis(timeout.toLong())
|
|
104
|
+
.build()
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
fusedLocationClient?.getCurrentLocation(request, null)
|
|
108
|
+
?.addOnSuccessListener { location ->
|
|
109
|
+
if (location != null) {
|
|
110
|
+
lastKnownLocation = location
|
|
111
|
+
call.resolve(buildLocationResult(location, cached = false))
|
|
112
|
+
} else {
|
|
113
|
+
val err = buildErrorEvent("POSITION_UNAVAILABLE", "Unable to get location")
|
|
114
|
+
notifyListeners("error", err)
|
|
115
|
+
call.reject("Unable to get location")
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
?.addOnFailureListener { e ->
|
|
119
|
+
val code = if (e is SecurityException) "PERMISSION_DENIED" else "POSITION_UNAVAILABLE"
|
|
120
|
+
val err = buildErrorEvent(code, "Location error: ${e.message}")
|
|
121
|
+
notifyListeners("error", err)
|
|
122
|
+
call.reject("Location error: ${e.message}")
|
|
123
|
+
}
|
|
124
|
+
} catch (e: SecurityException) {
|
|
125
|
+
val err = buildErrorEvent("PERMISSION_DENIED", "Location permission required")
|
|
126
|
+
notifyListeners("error", err)
|
|
127
|
+
call.reject("Location permission required")
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ── watchPosition ───────────────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
@PluginMethod
|
|
134
|
+
fun watchPosition(call: PluginCall) {
|
|
135
|
+
if (!hasRequiredPermissions()) {
|
|
136
|
+
pendingCall = call
|
|
137
|
+
pendingAction = "watchPosition"
|
|
138
|
+
requestAllPermissions(call, "handlePermissionResult")
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
watchPositionInternal(call)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private fun watchPositionInternal(call: PluginCall) {
|
|
145
|
+
val accuracy = call.getString("accuracy") ?: "high"
|
|
146
|
+
val minInterval = call.getDouble("minInterval") ?: 0.0
|
|
147
|
+
val minDistance = call.getDouble("minDistance") ?: 0.0
|
|
148
|
+
val priority = mapAccuracyToPriority(accuracy)
|
|
149
|
+
|
|
150
|
+
val watchId = UUID.randomUUID().toString()
|
|
151
|
+
|
|
152
|
+
val request = LocationRequest.Builder(priority, minInterval.toLong())
|
|
153
|
+
.setMinUpdateDistanceMeters(minDistance.toFloat())
|
|
154
|
+
.build()
|
|
155
|
+
|
|
156
|
+
val callback = object : LocationCallback() {
|
|
157
|
+
override fun onLocationResult(result: LocationResult) {
|
|
158
|
+
for (location in result.locations) {
|
|
159
|
+
lastKnownLocation = location
|
|
160
|
+
notifyListeners("locationChange", buildLocationResult(location, cached = false))
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
override fun onLocationAvailability(availability: LocationAvailability) {
|
|
165
|
+
if (!availability.isLocationAvailable) {
|
|
166
|
+
notifyListeners("error", buildErrorEvent(
|
|
167
|
+
"POSITION_UNAVAILABLE",
|
|
168
|
+
"Location services became unavailable"
|
|
169
|
+
))
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
fusedLocationClient?.requestLocationUpdates(
|
|
176
|
+
request,
|
|
177
|
+
callback,
|
|
178
|
+
Looper.getMainLooper()
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
watches[watchId] = callback
|
|
182
|
+
call.resolve(JSObject().apply {
|
|
183
|
+
put("watchId", watchId)
|
|
184
|
+
})
|
|
185
|
+
} catch (e: SecurityException) {
|
|
186
|
+
notifyListeners("error", buildErrorEvent("PERMISSION_DENIED", "Location permission required"))
|
|
187
|
+
call.reject("Location permission required")
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ── clearWatch ──────────────────────────────────────────────────────
|
|
192
|
+
|
|
193
|
+
@PluginMethod
|
|
194
|
+
fun clearWatch(call: PluginCall) {
|
|
195
|
+
val watchId = call.getString("watchId")
|
|
196
|
+
if (watchId == null) {
|
|
197
|
+
call.reject("Missing watchId")
|
|
198
|
+
return
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
val callback = watches.remove(watchId)
|
|
202
|
+
if (callback != null) {
|
|
203
|
+
fusedLocationClient?.removeLocationUpdates(callback)
|
|
204
|
+
}
|
|
205
|
+
call.resolve()
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ── Permissions ─────────────────────────────────────────────────────
|
|
209
|
+
|
|
210
|
+
@PluginMethod
|
|
211
|
+
override fun checkPermissions(call: PluginCall) {
|
|
212
|
+
call.resolve(buildPermissionResult())
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
@PluginMethod
|
|
216
|
+
override fun requestPermissions(call: PluginCall) {
|
|
217
|
+
if (hasRequiredPermissions()) {
|
|
218
|
+
call.resolve(buildPermissionResult())
|
|
219
|
+
return
|
|
220
|
+
}
|
|
221
|
+
pendingAction = "requestPermissions"
|
|
222
|
+
requestAllPermissions(call, "handlePermissionResult")
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
@PermissionCallback
|
|
226
|
+
private fun handlePermissionResult(call: PluginCall) {
|
|
227
|
+
if (hasRequiredPermissions()) {
|
|
228
|
+
when (pendingAction) {
|
|
229
|
+
"getCurrentPosition" -> {
|
|
230
|
+
pendingAction = null
|
|
231
|
+
pendingCall = null
|
|
232
|
+
getCurrentPositionInternal(call)
|
|
233
|
+
}
|
|
234
|
+
"watchPosition" -> {
|
|
235
|
+
pendingAction = null
|
|
236
|
+
pendingCall = null
|
|
237
|
+
watchPositionInternal(call)
|
|
238
|
+
}
|
|
239
|
+
else -> {
|
|
240
|
+
pendingAction = null
|
|
241
|
+
pendingCall = null
|
|
242
|
+
call.resolve(buildPermissionResult())
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
pendingAction = null
|
|
247
|
+
pendingCall = null
|
|
248
|
+
notifyListeners("error", buildErrorEvent("PERMISSION_DENIED", "Location permission denied"))
|
|
249
|
+
call.reject("Location permission denied")
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
254
|
+
|
|
255
|
+
override fun hasRequiredPermissions(): Boolean {
|
|
256
|
+
return getPermissionState("location") == com.getcapacitor.PermissionState.GRANTED
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** Map accuracy string from JS to Play Services Priority constant. */
|
|
260
|
+
private fun mapAccuracyToPriority(accuracy: String): Int {
|
|
261
|
+
return when (accuracy) {
|
|
262
|
+
"best" -> Priority.PRIORITY_HIGH_ACCURACY
|
|
263
|
+
"high" -> Priority.PRIORITY_HIGH_ACCURACY
|
|
264
|
+
"medium" -> Priority.PRIORITY_BALANCED_POWER_ACCURACY
|
|
265
|
+
"low" -> Priority.PRIORITY_LOW_POWER
|
|
266
|
+
"passive" -> Priority.PRIORITY_PASSIVE
|
|
267
|
+
else -> Priority.PRIORITY_HIGH_ACCURACY
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private fun buildPermissionResult(): JSObject {
|
|
272
|
+
val locationState = getPermissionState("location")
|
|
273
|
+
val locationStatus = when (locationState) {
|
|
274
|
+
com.getcapacitor.PermissionState.GRANTED -> "granted"
|
|
275
|
+
com.getcapacitor.PermissionState.DENIED -> "denied"
|
|
276
|
+
else -> "prompt"
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
val result = JSObject().apply {
|
|
280
|
+
put("location", locationStatus)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Background location is a separate permission on Android 10+
|
|
284
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
285
|
+
val bgGranted = ContextCompat.checkSelfPermission(
|
|
286
|
+
context, Manifest.permission.ACCESS_BACKGROUND_LOCATION
|
|
287
|
+
) == PackageManager.PERMISSION_GRANTED
|
|
288
|
+
|
|
289
|
+
val bgStatus = when {
|
|
290
|
+
bgGranted -> "granted"
|
|
291
|
+
// If foreground isn't granted, background is implicitly denied
|
|
292
|
+
locationStatus != "granted" -> "denied"
|
|
293
|
+
else -> "prompt"
|
|
294
|
+
}
|
|
295
|
+
result.put("background", bgStatus)
|
|
296
|
+
} else {
|
|
297
|
+
// Pre-Q: background is granted with foreground
|
|
298
|
+
result.put("background", locationStatus)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return result
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
private fun buildLocationResult(location: Location, cached: Boolean): JSObject {
|
|
305
|
+
val coords = JSObject().apply {
|
|
306
|
+
put("latitude", location.latitude)
|
|
307
|
+
put("longitude", location.longitude)
|
|
308
|
+
if (location.hasAltitude()) {
|
|
309
|
+
put("altitude", location.altitude)
|
|
310
|
+
}
|
|
311
|
+
put("accuracy", location.accuracy.toDouble())
|
|
312
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && location.hasVerticalAccuracy()) {
|
|
313
|
+
put("altitudeAccuracy", location.verticalAccuracyMeters.toDouble())
|
|
314
|
+
}
|
|
315
|
+
if (location.hasSpeed()) {
|
|
316
|
+
put("speed", location.speed.toDouble())
|
|
317
|
+
}
|
|
318
|
+
if (location.hasBearing()) {
|
|
319
|
+
put("heading", location.bearing.toDouble())
|
|
320
|
+
}
|
|
321
|
+
put("timestamp", location.time)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return JSObject().apply {
|
|
325
|
+
put("coords", coords)
|
|
326
|
+
put("cached", cached)
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
private fun buildErrorEvent(code: String, message: String): JSObject {
|
|
331
|
+
return JSObject().apply {
|
|
332
|
+
put("code", code)
|
|
333
|
+
put("message", message)
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ── Lifecycle ───────────────────────────────────────────────────────
|
|
338
|
+
|
|
339
|
+
override fun handleOnDestroy() {
|
|
340
|
+
super.handleOnDestroy()
|
|
341
|
+
for ((_, callback) in watches) {
|
|
342
|
+
fusedLocationClient?.removeLocationUpdates(callback)
|
|
343
|
+
}
|
|
344
|
+
watches.clear()
|
|
345
|
+
}
|
|
346
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { PluginListenerHandle } from "@capacitor/core";
|
|
2
|
+
/**
|
|
3
|
+
* Location accuracy level
|
|
4
|
+
*/
|
|
5
|
+
export type LocationAccuracy = "best" | "high" | "medium" | "low" | "passive";
|
|
6
|
+
/**
|
|
7
|
+
* Location coordinates
|
|
8
|
+
*/
|
|
9
|
+
export interface LocationCoordinates {
|
|
10
|
+
/** Latitude in degrees */
|
|
11
|
+
latitude: number;
|
|
12
|
+
/** Longitude in degrees */
|
|
13
|
+
longitude: number;
|
|
14
|
+
/** Altitude in meters (if available) */
|
|
15
|
+
altitude?: number;
|
|
16
|
+
/** Horizontal accuracy in meters */
|
|
17
|
+
accuracy: number;
|
|
18
|
+
/** Vertical accuracy in meters (if available) */
|
|
19
|
+
altitudeAccuracy?: number;
|
|
20
|
+
/** Speed in meters per second (if available) */
|
|
21
|
+
speed?: number;
|
|
22
|
+
/** Heading in degrees (if available) */
|
|
23
|
+
heading?: number;
|
|
24
|
+
/** Timestamp of the location */
|
|
25
|
+
timestamp: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Options for getting location
|
|
29
|
+
*/
|
|
30
|
+
export interface LocationOptions {
|
|
31
|
+
/** Desired accuracy level (default: high) */
|
|
32
|
+
accuracy?: LocationAccuracy;
|
|
33
|
+
/** Maximum age of cached location in milliseconds (default: 0 = no cache) */
|
|
34
|
+
maxAge?: number;
|
|
35
|
+
/** Timeout in milliseconds (default: 10000) */
|
|
36
|
+
timeout?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Options for watching location
|
|
40
|
+
*/
|
|
41
|
+
export interface WatchLocationOptions extends LocationOptions {
|
|
42
|
+
/** Minimum distance in meters to trigger an update (default: 0) */
|
|
43
|
+
minDistance?: number;
|
|
44
|
+
/** Minimum time interval in milliseconds between updates (default: 0) */
|
|
45
|
+
minInterval?: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Location result
|
|
49
|
+
*/
|
|
50
|
+
export interface LocationResult {
|
|
51
|
+
/** The location coordinates */
|
|
52
|
+
coords: LocationCoordinates;
|
|
53
|
+
/** Whether this is from cache */
|
|
54
|
+
cached: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Location permission status
|
|
58
|
+
*/
|
|
59
|
+
export interface LocationPermissionStatus {
|
|
60
|
+
/** Current permission status */
|
|
61
|
+
location: "granted" | "denied" | "prompt";
|
|
62
|
+
/** Whether background location is allowed (iOS/Android) */
|
|
63
|
+
background?: "granted" | "denied" | "prompt";
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Location error event
|
|
67
|
+
*/
|
|
68
|
+
export interface LocationErrorEvent {
|
|
69
|
+
/** Error code */
|
|
70
|
+
code: "PERMISSION_DENIED" | "POSITION_UNAVAILABLE" | "TIMEOUT" | "UNKNOWN";
|
|
71
|
+
/** Error message */
|
|
72
|
+
message: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Location Plugin Interface
|
|
76
|
+
*
|
|
77
|
+
* Provides access to device location services including GPS, network,
|
|
78
|
+
* and fused location providers.
|
|
79
|
+
*/
|
|
80
|
+
export interface LocationPlugin {
|
|
81
|
+
/**
|
|
82
|
+
* Get the current location
|
|
83
|
+
*
|
|
84
|
+
* @param options - Location options
|
|
85
|
+
* @returns Promise resolving to location result
|
|
86
|
+
*/
|
|
87
|
+
getCurrentPosition(options?: LocationOptions): Promise<LocationResult>;
|
|
88
|
+
/**
|
|
89
|
+
* Start watching location changes
|
|
90
|
+
*
|
|
91
|
+
* Location updates are delivered via the 'locationChange' event.
|
|
92
|
+
*
|
|
93
|
+
* @param options - Watch options
|
|
94
|
+
* @returns Promise resolving to a watch ID
|
|
95
|
+
*/
|
|
96
|
+
watchPosition(options?: WatchLocationOptions): Promise<{
|
|
97
|
+
watchId: string;
|
|
98
|
+
}>;
|
|
99
|
+
/**
|
|
100
|
+
* Stop watching location changes
|
|
101
|
+
*
|
|
102
|
+
* @param options - Watch ID to stop
|
|
103
|
+
* @returns Promise that resolves when watch is stopped
|
|
104
|
+
*/
|
|
105
|
+
clearWatch(options: {
|
|
106
|
+
watchId: string;
|
|
107
|
+
}): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Check location permission status
|
|
110
|
+
*
|
|
111
|
+
* @returns Promise resolving to permission status
|
|
112
|
+
*/
|
|
113
|
+
checkPermissions(): Promise<LocationPermissionStatus>;
|
|
114
|
+
/**
|
|
115
|
+
* Request location permissions
|
|
116
|
+
*
|
|
117
|
+
* @returns Promise resolving to permission status after request
|
|
118
|
+
*/
|
|
119
|
+
requestPermissions(): Promise<LocationPermissionStatus>;
|
|
120
|
+
/**
|
|
121
|
+
* Add listener for location changes (when watching)
|
|
122
|
+
*/
|
|
123
|
+
addListener(eventName: "locationChange", listenerFunc: (location: LocationResult) => void): Promise<PluginListenerHandle>;
|
|
124
|
+
/**
|
|
125
|
+
* Add listener for location errors
|
|
126
|
+
*/
|
|
127
|
+
addListener(eventName: "error", listenerFunc: (error: LocationErrorEvent) => void): Promise<PluginListenerHandle>;
|
|
128
|
+
/**
|
|
129
|
+
* Remove all listeners
|
|
130
|
+
*/
|
|
131
|
+
removeAllListeners(): Promise<void>;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=definitions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAE5D;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;AAE9E;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IAC3D,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,+BAA+B;IAC/B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,iCAAiC;IACjC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,gCAAgC;IAChC,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC1C,2DAA2D;IAC3D,UAAU,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iBAAiB;IACjB,IAAI,EAAE,mBAAmB,GAAG,sBAAsB,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3E,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,kBAAkB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAEvE;;;;;;;OAOG;IACH,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE5E;;;;;OAKG;IACH,UAAU,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD;;;;OAIG;IACH,gBAAgB,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAEtD;;;;OAIG;IACH,kBAAkB,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAExD;;OAEG;IACH,WAAW,CACT,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,GAC/C,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjC;;OAEG;IACH,WAAW,CACT,SAAS,EAAE,OAAO,EAClB,YAAY,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAChD,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjC;;OAEG;IACH,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,cAAc,eAAe,CAAC;AAI9B,eAAO,MAAM,QAAQ,gBAEnB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { registerPlugin } from "@capacitor/core";
|
|
2
|
+
export * from "./definitions";
|
|
3
|
+
const loadWeb = () => import("./web").then((m) => new m.LocationWeb());
|
|
4
|
+
export const Location = registerPlugin("ElizaLocation", {
|
|
5
|
+
web: loadWeb,
|
|
6
|
+
});
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,cAAc,eAAe,CAAC;AAE9B,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAEvE,MAAM,CAAC,MAAM,QAAQ,GAAG,cAAc,CAAiB,eAAe,EAAE;IACtE,GAAG,EAAE,OAAO;CACb,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { WebPlugin } from "@capacitor/core";
|
|
2
|
+
import type { LocationOptions, LocationPermissionStatus, LocationResult, WatchLocationOptions } from "./definitions";
|
|
3
|
+
/**
|
|
4
|
+
* Web implementation of the Location Plugin
|
|
5
|
+
*
|
|
6
|
+
* Uses the browser Geolocation API.
|
|
7
|
+
*/
|
|
8
|
+
export declare class LocationWeb extends WebPlugin {
|
|
9
|
+
private watches;
|
|
10
|
+
getCurrentPosition(options?: LocationOptions): Promise<LocationResult>;
|
|
11
|
+
watchPosition(options?: WatchLocationOptions): Promise<{
|
|
12
|
+
watchId: string;
|
|
13
|
+
}>;
|
|
14
|
+
clearWatch(options: {
|
|
15
|
+
watchId: string;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
checkPermissions(): Promise<LocationPermissionStatus>;
|
|
18
|
+
requestPermissions(): Promise<LocationPermissionStatus>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,EACV,eAAe,EACf,wBAAwB,EACxB,cAAc,EACd,oBAAoB,EACrB,MAAM,eAAe,CAAC;AAEvB;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,SAAS;IACxC,OAAO,CAAC,OAAO,CAA6B;IAEtC,kBAAkB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAmDtE,aAAa,CACjB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAsDzB,UAAU,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQvD,gBAAgB,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAqBrD,kBAAkB,IAAI,OAAO,CAAC,wBAAwB,CAAC;CAc9D"}
|