@capgo/nativegeocoder 0.0.1
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/CapgoNativegeocoder.podspec +17 -0
- package/README.md +98 -0
- package/android/build.gradle +58 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/ee/forgr/plugin/nativegeocoder/NativeGeocoder.java +239 -0
- package/android/src/main/java/ee/forgr/plugin/nativegeocoder/NativeGeocoderPlugin.java +39 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +242 -0
- package/dist/esm/definitions.d.ts +37 -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.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +10 -0
- package/dist/esm/web.js +62 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +78 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +81 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/Info.plist +24 -0
- package/ios/Plugin/NativeGeocoder.swift +242 -0
- package/ios/Plugin/NativeGeocoderPlugin.h +10 -0
- package/ios/Plugin/NativeGeocoderPlugin.m +9 -0
- package/ios/Plugin/NativeGeocoderPlugin.swift +31 -0
- package/package.json +79 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import CoreLocation
|
|
3
|
+
|
|
4
|
+
struct NativeGeocoderResult: Encodable {
|
|
5
|
+
var latitude: String?
|
|
6
|
+
var longitude: String?
|
|
7
|
+
var countryCode: String?
|
|
8
|
+
var countryName: String?
|
|
9
|
+
var postalCode: String?
|
|
10
|
+
var administrativeArea: String?
|
|
11
|
+
var subAdministrativeArea: String?
|
|
12
|
+
var locality: String?
|
|
13
|
+
var subLocality: String?
|
|
14
|
+
var thoroughfare: String?
|
|
15
|
+
var subThoroughfare: String?
|
|
16
|
+
var areasOfInterest: [String]?
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
struct NativeGeocoderError {
|
|
20
|
+
var message: String
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
struct NativeGeocoderOptions: Decodable {
|
|
24
|
+
var useLocale: Bool = true
|
|
25
|
+
var defaultLocale: String?
|
|
26
|
+
var maxResults: Int = 1
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@objc public class NativeGeocoder: NSObject {
|
|
30
|
+
|
|
31
|
+
typealias ReverseGeocodeCompletionHandler = ([NativeGeocoderResult]?, NativeGeocoderError?) -> Void
|
|
32
|
+
typealias ForwardGeocodeCompletionHandler = ([NativeGeocoderResult]?, NativeGeocoderError?) -> Void
|
|
33
|
+
private static let MAX_RESULTS_COUNT = 5
|
|
34
|
+
|
|
35
|
+
// MARK: - REVERSE GEOCODE
|
|
36
|
+
@objc(reverseGeocode:) func reverseGeocode(latitude: Double, longitude: Double, call: CAPPluginCall) {
|
|
37
|
+
if (CLGeocoder().isGeocoding) {
|
|
38
|
+
call.reject("Geocoder is busy. Please try again later.")
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let location = CLLocation(latitude: latitude, longitude: longitude)
|
|
43
|
+
var options = NativeGeocoderOptions(useLocale: true, defaultLocale: nil, maxResults: 1)
|
|
44
|
+
options.useLocale = call.getBoolean("useLocale") ?? true
|
|
45
|
+
options.defaultLocale = call.getString()
|
|
46
|
+
options.maxResults = call.getNumber() ?? 1
|
|
47
|
+
|
|
48
|
+
reverseGeocodeLocationHandler(location, options: options, completionHandler: { [weak self] (resultObj, error) in
|
|
49
|
+
if let error = error {
|
|
50
|
+
call.reject(error.message)
|
|
51
|
+
} else {
|
|
52
|
+
if let encodedResult = try? JSONEncoder().encode(resultObj),
|
|
53
|
+
let result = try? JSONSerialization.jsonObject(with: encodedResult, options: .allowFragments) as? [Dictionary<String,Any>] {
|
|
54
|
+
call.resolve(result)
|
|
55
|
+
} else {
|
|
56
|
+
call.reject("Invalid JSON result")
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private func reverseGeocodeLocationHandler(_ location: CLLocation, options: NativeGeocoderOptions, completionHandler: @escaping ReverseGeocodeCompletionHandler) {
|
|
63
|
+
let geocoderOptions = getNativeGeocoderOptions(from: options)
|
|
64
|
+
|
|
65
|
+
if #available(iOS 11, *) {
|
|
66
|
+
var locale: Locale?
|
|
67
|
+
if let defaultLocaleString = geocoderOptions.defaultLocale {
|
|
68
|
+
locale = Locale.init(identifier: defaultLocaleString)
|
|
69
|
+
} else if (geocoderOptions.useLocale == false) {
|
|
70
|
+
locale = Locale.init(identifier: "en_US")
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
CLGeocoder().reverseGeocodeLocation(location, preferredLocale: locale, completionHandler: { [weak self] (placemarks, error) in
|
|
74
|
+
self?.createReverseGeocodeResult(placemarks, error, maxResults: geocoderOptions.maxResults, completionHandler: { (resultObj, error) in
|
|
75
|
+
completionHandler(resultObj, error)
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
} else {
|
|
79
|
+
// fallback for < iOS 11
|
|
80
|
+
CLGeocoder().reverseGeocodeLocation(location, completionHandler: { [weak self] (placemarks, error) in
|
|
81
|
+
self?.createReverseGeocodeResult(placemarks, error, maxResults: geocoderOptions.maxResults, completionHandler: { (resultObj, error) in
|
|
82
|
+
completionHandler(resultObj, error)
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private func createReverseGeocodeResult(_ placemarks: [CLPlacemark]?, _ error: Error?, maxResults: Int, completionHandler: @escaping ReverseGeocodeCompletionHandler) {
|
|
89
|
+
guard error == nil else {
|
|
90
|
+
completionHandler(nil, NativeGeocoderError(message: "CLGeocoder:reverseGeocodeLocation Error"))
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if let placemarks = placemarks {
|
|
95
|
+
let maxResultObjects = placemarks.count >= maxResults ? maxResults : placemarks.count
|
|
96
|
+
var resultObj = [NativeGeocoderResult]()
|
|
97
|
+
|
|
98
|
+
for i in 0..<maxResultObjects {
|
|
99
|
+
// https://developer.apple.com/documentation/corelocation/clplacemark
|
|
100
|
+
var latitude = ""
|
|
101
|
+
if let lat = placemarks[i].location?.coordinate.latitude {
|
|
102
|
+
latitude = "\(lat)"
|
|
103
|
+
}
|
|
104
|
+
var longitude = ""
|
|
105
|
+
if let lon = placemarks[i].location?.coordinate.longitude {
|
|
106
|
+
longitude = "\(lon)"
|
|
107
|
+
}
|
|
108
|
+
let placemark = NativeGeocoderResult(
|
|
109
|
+
latitude: latitude,
|
|
110
|
+
longitude: longitude,
|
|
111
|
+
countryCode: placemarks[i].isoCountryCode ?? "",
|
|
112
|
+
countryName: placemarks[i].country ?? "",
|
|
113
|
+
postalCode: placemarks[i].postalCode ?? "",
|
|
114
|
+
administrativeArea: placemarks[i].administrativeArea ?? "",
|
|
115
|
+
subAdministrativeArea: placemarks[i].subAdministrativeArea ?? "",
|
|
116
|
+
locality: placemarks[i].locality ?? "",
|
|
117
|
+
subLocality: placemarks[i].subLocality ?? "",
|
|
118
|
+
thoroughfare: placemarks[i].thoroughfare ?? "",
|
|
119
|
+
subThoroughfare: placemarks[i].subThoroughfare ?? "",
|
|
120
|
+
areasOfInterest: placemarks[i].areasOfInterest ?? []
|
|
121
|
+
)
|
|
122
|
+
resultObj.append(placemark)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
completionHandler(resultObj, nil)
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
completionHandler(nil, NativeGeocoderError(message: "Cannot get an address"))
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
// MARK: - FORWARD GEOCODE
|
|
134
|
+
@objc(forwardGeocode:)func forwardGeocode(address: String, call: CAPPluginCall) {
|
|
135
|
+
|
|
136
|
+
if (CLGeocoder().isGeocoding) {
|
|
137
|
+
call.reject("Geocoder is busy. Please try again later.")
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
var options = NativeGeocoderOptions(useLocale: true, defaultLocale: nil, maxResults: 1)
|
|
142
|
+
options.useLocale = call.getBoolean("useLocale") ?? true
|
|
143
|
+
options.defaultLocale = call.getString()
|
|
144
|
+
options.maxResults = call.getNumber() ?? 1
|
|
145
|
+
|
|
146
|
+
forwardGeocodeHandler(address, options: options, completionHandler: { [weak self] (resultObj, error) in
|
|
147
|
+
if let error = error {
|
|
148
|
+
call.reject(error.message)
|
|
149
|
+
} else {
|
|
150
|
+
if let encodedResult = try? JSONEncoder().encode(resultObj),
|
|
151
|
+
let result = try? JSONSerialization.jsonObject(with: encodedResult, options: .allowFragments) as? [Dictionary<String,Any>] {
|
|
152
|
+
call.resolve(result)
|
|
153
|
+
} else {
|
|
154
|
+
call.reject("Invalid JSON result")
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
func forwardGeocodeHandler(_ address: String, options: NativeGeocoderOptions, completionHandler: @escaping ForwardGeocodeCompletionHandler) {
|
|
161
|
+
let geocoderOptions = getNativeGeocoderOptions(from: options)
|
|
162
|
+
|
|
163
|
+
if #available(iOS 11, *) {
|
|
164
|
+
var locale: Locale?
|
|
165
|
+
if let defaultLocaleString = geocoderOptions.defaultLocale {
|
|
166
|
+
locale = Locale.init(identifier: defaultLocaleString)
|
|
167
|
+
} else if (geocoderOptions.useLocale == false) {
|
|
168
|
+
locale = Locale.init(identifier: "en_US")
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
CLGeocoder().geocodeAddressString(address, in: nil, preferredLocale: locale, completionHandler: { [weak self] (placemarks, error) in
|
|
172
|
+
self?.createForwardGeocodeResult(placemarks, error, maxResults: geocoderOptions.maxResults, completionHandler: { (resultObj, error) in
|
|
173
|
+
completionHandler(resultObj, error)
|
|
174
|
+
})
|
|
175
|
+
})
|
|
176
|
+
} else {
|
|
177
|
+
// fallback for < iOS 11
|
|
178
|
+
CLGeocoder().geocodeAddressString(address, completionHandler: { [weak self] (placemarks, error) in
|
|
179
|
+
self?.createForwardGeocodeResult(placemarks, error, maxResults: geocoderOptions.maxResults, completionHandler: { (resultObj, error) in
|
|
180
|
+
completionHandler(resultObj, error)
|
|
181
|
+
})
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private func createForwardGeocodeResult(_ placemarks: [CLPlacemark]?, _ error: Error?, maxResults: Int, completionHandler: @escaping ForwardGeocodeCompletionHandler) {
|
|
187
|
+
guard error == nil else {
|
|
188
|
+
completionHandler(nil, NativeGeocoderError(message: "CLGeocoder:geocodeAddressString Error"))
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if let placemarks = placemarks {
|
|
193
|
+
let maxResultObjects = placemarks.count >= maxResults ? maxResults : placemarks.count
|
|
194
|
+
var resultObj = [NativeGeocoderResult]()
|
|
195
|
+
|
|
196
|
+
for i in 0..<maxResultObjects {
|
|
197
|
+
if let latitude = placemarks[i].location?.coordinate.latitude,
|
|
198
|
+
let longitude = placemarks[i].location?.coordinate.longitude {
|
|
199
|
+
|
|
200
|
+
// https://developer.apple.com/documentation/corelocation/clplacemark
|
|
201
|
+
let placemark = NativeGeocoderResult(
|
|
202
|
+
latitude: "\(latitude)",
|
|
203
|
+
longitude: "\(longitude)",
|
|
204
|
+
countryCode: placemarks[i].isoCountryCode ?? "",
|
|
205
|
+
countryName: placemarks[i].country ?? "",
|
|
206
|
+
postalCode: placemarks[i].postalCode ?? "",
|
|
207
|
+
administrativeArea: placemarks[i].administrativeArea ?? "",
|
|
208
|
+
subAdministrativeArea: placemarks[i].subAdministrativeArea ?? "",
|
|
209
|
+
locality: placemarks[i].locality ?? "",
|
|
210
|
+
subLocality: placemarks[i].subLocality ?? "",
|
|
211
|
+
thoroughfare: placemarks[i].thoroughfare ?? "",
|
|
212
|
+
subThoroughfare: placemarks[i].subThoroughfare ?? "",
|
|
213
|
+
areasOfInterest: placemarks[i].areasOfInterest ?? []
|
|
214
|
+
)
|
|
215
|
+
resultObj.append(placemark)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (resultObj.count == 0) {
|
|
220
|
+
completionHandler(nil, NativeGeocoderError(message: "Cannot get latitude and/or longitude"))
|
|
221
|
+
} else {
|
|
222
|
+
completionHandler(resultObj, nil)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
completionHandler(nil, NativeGeocoderError(message: "Cannot find a location"))
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// MARK: - Helper
|
|
231
|
+
private func getNativeGeocoderOptions(from options: NativeGeocoderOptions) -> NativeGeocoderOptions {
|
|
232
|
+
var geocoderOptions = NativeGeocoderOptions()
|
|
233
|
+
geocoderOptions.useLocale = options.useLocale
|
|
234
|
+
geocoderOptions.defaultLocale = options.defaultLocale
|
|
235
|
+
if (options.maxResults > 0) {
|
|
236
|
+
geocoderOptions.maxResults = options.maxResults > NativeGeocoder.MAX_RESULTS_COUNT ? NativeGeocoder.MAX_RESULTS_COUNT : options.maxResults
|
|
237
|
+
} else {
|
|
238
|
+
geocoderOptions.maxResults = 1
|
|
239
|
+
}
|
|
240
|
+
return geocoderOptions
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
|
|
3
|
+
//! Project version number for Plugin.
|
|
4
|
+
FOUNDATION_EXPORT double PluginVersionNumber;
|
|
5
|
+
|
|
6
|
+
//! Project version string for Plugin.
|
|
7
|
+
FOUNDATION_EXPORT const unsigned char PluginVersionString[];
|
|
8
|
+
|
|
9
|
+
// In this header, you should import all the public headers of your framework using statements like #import <Plugin/PublicHeader.h>
|
|
10
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <Capacitor/Capacitor.h>
|
|
3
|
+
|
|
4
|
+
// Define the plugin using the CAP_PLUGIN Macro, and
|
|
5
|
+
// each method the plugin supports using the CAP_PLUGIN_METHOD macro.
|
|
6
|
+
CAP_PLUGIN(NativeGeocoderPlugin, "NativeGeocoder",
|
|
7
|
+
CAP_PLUGIN_METHOD(reverseGeocode, CAPPluginReturnPromise);
|
|
8
|
+
CAP_PLUGIN_METHOD(forwardGeocode, CAPPluginReturnPromise);
|
|
9
|
+
)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Please read the Capacitor iOS Plugin Development Guide
|
|
6
|
+
* here: https://capacitorjs.com/docs/plugins/ios
|
|
7
|
+
*/
|
|
8
|
+
@objc(NativeGeocoderPlugin)
|
|
9
|
+
public class NativeGeocoderPlugin: CAPPlugin {
|
|
10
|
+
private let implementation = NativeGeocoder()
|
|
11
|
+
|
|
12
|
+
@objc func reverseGeocode(_ call: CAPPluginCall) {
|
|
13
|
+
guard let addressString = call.getString("addressString") else {
|
|
14
|
+
call.reject("Missing addressString")
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
implementation.reverseGeocode(addressString: addressString, call: call)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@objc func forwardGeocode(_ call: CAPPluginCall) {
|
|
21
|
+
guard let latitude = call.getNumber("latitude") else {
|
|
22
|
+
call.reject("Missing latitude")
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
guard let longitude = call.getNumber("longitude") else {
|
|
26
|
+
call.reject("Missing longitude")
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
implementation.forwardGeocode(latitude: latitude, longitude: longitude, call: call)
|
|
30
|
+
}
|
|
31
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@capgo/nativegeocoder",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Capacitor plugin for native forward and reverse geocoding",
|
|
5
|
+
"main": "dist/plugin.cjs.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
7
|
+
"types": "dist/esm/index.d.ts",
|
|
8
|
+
"unpkg": "dist/plugin.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"android/src/main/",
|
|
11
|
+
"android/build.gradle",
|
|
12
|
+
"dist/",
|
|
13
|
+
"ios/Plugin/",
|
|
14
|
+
"CapgoNativegeocoder.podspec"
|
|
15
|
+
],
|
|
16
|
+
"author": "Martin Donadieu",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/Cap-go/capacitor-nativegeocoder.git"
|
|
21
|
+
},
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/Cap-go/capacitor-nativegeocoder/issues"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"capacitor",
|
|
27
|
+
"plugin",
|
|
28
|
+
"geocoder",
|
|
29
|
+
"native"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
|
|
33
|
+
"verify:ios": "cd ios && pod install && xcodebuild -workspace Plugin.xcworkspace -scheme Plugin && cd ..",
|
|
34
|
+
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
35
|
+
"verify:web": "npm run build",
|
|
36
|
+
"lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
|
|
37
|
+
"fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
|
|
38
|
+
"eslint": "eslint . --ext ts",
|
|
39
|
+
"prettier": "prettier \"**/*.{css,html,ts,js,java}\"",
|
|
40
|
+
"swiftlint": "node-swiftlint",
|
|
41
|
+
"docgen": "docgen --api NativeGeocoderPlugin --output-readme README.md --output-json dist/docs.json",
|
|
42
|
+
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.js",
|
|
43
|
+
"clean": "rimraf ./dist",
|
|
44
|
+
"watch": "tsc --watch",
|
|
45
|
+
"prepublishOnly": "npm run build"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@capacitor/android": "^3.0.0",
|
|
49
|
+
"@capacitor/core": "^3.0.0",
|
|
50
|
+
"@capacitor/docgen": "^0.0.18",
|
|
51
|
+
"@capacitor/ios": "^3.0.0",
|
|
52
|
+
"@ionic/eslint-config": "^0.3.0",
|
|
53
|
+
"@ionic/prettier-config": "^1.0.1",
|
|
54
|
+
"@ionic/swiftlint-config": "^1.1.2",
|
|
55
|
+
"eslint": "^7.11.0",
|
|
56
|
+
"prettier": "~2.2.0",
|
|
57
|
+
"prettier-plugin-java": "~1.0.0",
|
|
58
|
+
"rimraf": "^3.0.2",
|
|
59
|
+
"rollup": "^2.32.0",
|
|
60
|
+
"swiftlint": "^1.0.1",
|
|
61
|
+
"typescript": "~4.0.3"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"@capacitor/core": "^3.0.0"
|
|
65
|
+
},
|
|
66
|
+
"prettier": "@ionic/prettier-config",
|
|
67
|
+
"swiftlint": "@ionic/swiftlint-config",
|
|
68
|
+
"eslintConfig": {
|
|
69
|
+
"extends": "@ionic/eslint-config/recommended"
|
|
70
|
+
},
|
|
71
|
+
"capacitor": {
|
|
72
|
+
"ios": {
|
|
73
|
+
"src": "ios"
|
|
74
|
+
},
|
|
75
|
+
"android": {
|
|
76
|
+
"src": "android"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|