@capgo/capacitor-launch-navigator 8.0.20 → 8.0.22
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/README.md +200 -15
- package/android/src/main/AndroidManifest.xml +10 -0
- package/android/src/main/java/app/capgo/plugin/launch_navigator/LaunchNavigator.java +847 -71
- package/android/src/main/java/app/capgo/plugin/launch_navigator/LaunchNavigatorPlugin.java +62 -2
- package/dist/docs.json +358 -0
- package/dist/esm/definitions.d.ts +180 -1
- package/dist/esm/definitions.js +12 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +8 -2
- package/dist/esm/web.js +332 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +344 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +344 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/LaunchNavigatorPlugin/LaunchNavigator.swift +228 -19
- package/ios/Sources/LaunchNavigatorPlugin/LaunchNavigatorIcons.swift +447 -0
- package/ios/Sources/LaunchNavigatorPlugin/LaunchNavigatorPlugin.swift +47 -2
- package/ios/Tests/LaunchNavigatorPluginTests/LaunchNavigatorPluginTests.swift +16 -6
- package/package.json +1 -1
|
@@ -2,29 +2,44 @@ import Foundation
|
|
|
2
2
|
import UIKit
|
|
3
3
|
import MapKit
|
|
4
4
|
|
|
5
|
+
struct NavigationAppInfo {
|
|
6
|
+
let name: String
|
|
7
|
+
let urlScheme: String
|
|
8
|
+
let url: String
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// swiftlint:disable type_body_length
|
|
5
12
|
@objc public class LaunchNavigator: NSObject {
|
|
6
13
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
14
|
+
public var webPathResolver: ((URL) -> String?)?
|
|
15
|
+
|
|
16
|
+
let navigationApps: [String: NavigationAppInfo] = [
|
|
17
|
+
"apple_maps": NavigationAppInfo(name: "Apple Maps", urlScheme: "maps://", url: "https://www.apple.com/maps/"),
|
|
18
|
+
"google_maps": NavigationAppInfo(name: "Google Maps", urlScheme: "comgooglemaps://", url: "https://www.google.com/maps"),
|
|
19
|
+
"waze": NavigationAppInfo(name: "Waze", urlScheme: "waze://", url: "https://www.waze.com"),
|
|
20
|
+
"citymapper": NavigationAppInfo(name: "Citymapper", urlScheme: "citymapper://", url: "https://citymapper.com"),
|
|
21
|
+
"garmin_navigon": NavigationAppInfo(name: "Garmin Navigon", urlScheme: "navigon://", url: "https://www.garmin.com"),
|
|
22
|
+
"transit_app": NavigationAppInfo(name: "Transit App", urlScheme: "transit://", url: "https://transitapp.com"),
|
|
23
|
+
"yandex": NavigationAppInfo(name: "Yandex Navigator", urlScheme: "yandexnavi://", url: "https://yandex.com/maps"),
|
|
24
|
+
"uber": NavigationAppInfo(name: "Uber", urlScheme: "uber://", url: "https://www.uber.com"),
|
|
25
|
+
"tomtom": NavigationAppInfo(name: "TomTom", urlScheme: "tomtomgo://", url: "https://www.tomtom.com"),
|
|
26
|
+
"sygic": NavigationAppInfo(name: "Sygic", urlScheme: "com.sygic.aura://", url: "https://www.sygic.com/gps-navigation"),
|
|
27
|
+
"here": NavigationAppInfo(name: "HERE Maps", urlScheme: "here-route://", url: "https://wego.here.com"),
|
|
28
|
+
"moovit": NavigationAppInfo(name: "Moovit", urlScheme: "moovit://", url: "https://moovitapp.com"),
|
|
29
|
+
"lyft": NavigationAppInfo(name: "Lyft", urlScheme: "lyft://", url: "https://www.lyft.com"),
|
|
30
|
+
"mapsme": NavigationAppInfo(name: "MAPS.ME", urlScheme: "mapsme://", url: "https://maps.me"),
|
|
31
|
+
"guru_maps": NavigationAppInfo(name: "Guru Maps", urlScheme: "guru://", url: "https://gurumaps.app"),
|
|
32
|
+
"organic_maps": NavigationAppInfo(name: "Organic Maps", urlScheme: "om://", url: "https://organicmaps.app"),
|
|
33
|
+
"yandex_maps": NavigationAppInfo(name: "Yandex Maps", urlScheme: "yandexmaps://", url: "https://yandex.com/maps"),
|
|
34
|
+
"2gis": NavigationAppInfo(name: "2GIS", urlScheme: "dgis://", url: "https://2gis.com"),
|
|
35
|
+
"cabify": NavigationAppInfo(name: "Cabify", urlScheme: "cabify://", url: "https://cabify.com"),
|
|
36
|
+
"baidu": NavigationAppInfo(name: "Baidu Maps", urlScheme: "baidumap://", url: "https://map.baidu.com"),
|
|
37
|
+
"gaode": NavigationAppInfo(name: "Gaode Maps", urlScheme: "iosamap://", url: "https://www.amap.com"),
|
|
38
|
+
"tesla": NavigationAppInfo(name: "Tesla", urlScheme: "tesla://", url: "https://www.tesla.com"),
|
|
39
|
+
"99taxi": NavigationAppInfo(name: "99 Taxi", urlScheme: "99app://", url: "https://99app.com")
|
|
26
40
|
]
|
|
27
41
|
|
|
42
|
+
// swiftlint:disable:next cyclomatic_complexity function_body_length function_parameter_count
|
|
28
43
|
public func navigate(
|
|
29
44
|
app: String,
|
|
30
45
|
destination: CLLocationCoordinate2D,
|
|
@@ -32,6 +47,7 @@ import MapKit
|
|
|
32
47
|
startName: String?,
|
|
33
48
|
destinationName: String?,
|
|
34
49
|
transportMode: String,
|
|
50
|
+
viewController: UIViewController? = nil,
|
|
35
51
|
completion: @escaping (Bool, String?) -> Void
|
|
36
52
|
) {
|
|
37
53
|
switch app {
|
|
@@ -106,6 +122,34 @@ import MapKit
|
|
|
106
122
|
destination: destination,
|
|
107
123
|
completion: completion
|
|
108
124
|
)
|
|
125
|
+
case "guru_maps":
|
|
126
|
+
launchGuruMaps(
|
|
127
|
+
destination: destination,
|
|
128
|
+
start: start,
|
|
129
|
+
transportMode: transportMode,
|
|
130
|
+
completion: completion
|
|
131
|
+
)
|
|
132
|
+
case "organic_maps":
|
|
133
|
+
launchOrganicMaps(
|
|
134
|
+
destination: destination,
|
|
135
|
+
start: start,
|
|
136
|
+
destinationName: destinationName,
|
|
137
|
+
transportMode: transportMode,
|
|
138
|
+
completion: completion
|
|
139
|
+
)
|
|
140
|
+
case "yandex_maps":
|
|
141
|
+
launchYandexMaps(
|
|
142
|
+
destination: destination,
|
|
143
|
+
start: start,
|
|
144
|
+
completion: completion
|
|
145
|
+
)
|
|
146
|
+
case "2gis":
|
|
147
|
+
launch2Gis(
|
|
148
|
+
destination: destination,
|
|
149
|
+
start: start,
|
|
150
|
+
transportMode: transportMode,
|
|
151
|
+
completion: completion
|
|
152
|
+
)
|
|
109
153
|
case "cabify":
|
|
110
154
|
launchCabify(
|
|
111
155
|
destination: destination,
|
|
@@ -124,6 +168,13 @@ import MapKit
|
|
|
124
168
|
start: start,
|
|
125
169
|
completion: completion
|
|
126
170
|
)
|
|
171
|
+
case "tesla":
|
|
172
|
+
shareToTesla(
|
|
173
|
+
destination: destination,
|
|
174
|
+
destinationName: destinationName,
|
|
175
|
+
viewController: viewController,
|
|
176
|
+
completion: completion
|
|
177
|
+
)
|
|
127
178
|
default:
|
|
128
179
|
completion(false, "Unsupported navigation app: \(app)")
|
|
129
180
|
}
|
|
@@ -300,6 +351,103 @@ import MapKit
|
|
|
300
351
|
openURL(urlString, completion: completion)
|
|
301
352
|
}
|
|
302
353
|
|
|
354
|
+
private func launchGuruMaps(
|
|
355
|
+
destination: CLLocationCoordinate2D,
|
|
356
|
+
start: CLLocationCoordinate2D?,
|
|
357
|
+
transportMode: String,
|
|
358
|
+
completion: @escaping (Bool, String?) -> Void
|
|
359
|
+
) {
|
|
360
|
+
var urlString = "guru://nav?finish=\(destination.latitude),\(destination.longitude)&mode=\(guruMapsMode(transportMode))&start_navigation=true"
|
|
361
|
+
|
|
362
|
+
if let startCoord = start {
|
|
363
|
+
urlString += "&start=\(startCoord.latitude),\(startCoord.longitude)"
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
openURL(urlString, completion: completion)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
private func guruMapsMode(_ transportMode: String) -> String {
|
|
370
|
+
switch transportMode {
|
|
371
|
+
case "walking":
|
|
372
|
+
return "pedestrian"
|
|
373
|
+
case "bicycling":
|
|
374
|
+
return "bicycle"
|
|
375
|
+
default:
|
|
376
|
+
return "auto"
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
private func launchOrganicMaps(
|
|
381
|
+
destination: CLLocationCoordinate2D,
|
|
382
|
+
start: CLLocationCoordinate2D?,
|
|
383
|
+
destinationName: String?,
|
|
384
|
+
transportMode: String,
|
|
385
|
+
completion: @escaping (Bool, String?) -> Void
|
|
386
|
+
) {
|
|
387
|
+
let origin = start.map { "\($0.latitude),\($0.longitude)" } ?? "currentLocation"
|
|
388
|
+
var urlString = "om://v2/nav?origin=\(encoded(origin))&destination=\(destination.latitude),\(destination.longitude)&mode=\(organicMapsMode(transportMode))"
|
|
389
|
+
|
|
390
|
+
if let destinationName = destinationName, !destinationName.isEmpty {
|
|
391
|
+
urlString += "&destination_name=\(encoded(destinationName))"
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
openURL(urlString, completion: completion)
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
private func organicMapsMode(_ transportMode: String) -> String {
|
|
398
|
+
switch transportMode {
|
|
399
|
+
case "walking":
|
|
400
|
+
return "pedestrian"
|
|
401
|
+
case "bicycling":
|
|
402
|
+
return "bicycle"
|
|
403
|
+
case "transit":
|
|
404
|
+
return "transit"
|
|
405
|
+
default:
|
|
406
|
+
return "drive"
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
private func launchYandexMaps(
|
|
411
|
+
destination: CLLocationCoordinate2D,
|
|
412
|
+
start: CLLocationCoordinate2D?,
|
|
413
|
+
completion: @escaping (Bool, String?) -> Void
|
|
414
|
+
) {
|
|
415
|
+
var urlString = "yandexmaps://build_route_on_map/?lat_to=\(destination.latitude)&lon_to=\(destination.longitude)"
|
|
416
|
+
|
|
417
|
+
if let startCoord = start {
|
|
418
|
+
urlString += "&lat_from=\(startCoord.latitude)&lon_from=\(startCoord.longitude)"
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
openURL(urlString, completion: completion)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
private func launch2Gis(
|
|
425
|
+
destination: CLLocationCoordinate2D,
|
|
426
|
+
start: CLLocationCoordinate2D?,
|
|
427
|
+
transportMode: String,
|
|
428
|
+
completion: @escaping (Bool, String?) -> Void
|
|
429
|
+
) {
|
|
430
|
+
var urlString = "dgis://2gis.ru/routeSearch/rsType/\(twoGisMode(transportMode))"
|
|
431
|
+
|
|
432
|
+
if let startCoord = start {
|
|
433
|
+
urlString += "/from/\(startCoord.longitude),\(startCoord.latitude)"
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
urlString += "/to/\(destination.longitude),\(destination.latitude)"
|
|
437
|
+
openURL(urlString, completion: completion)
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
private func twoGisMode(_ transportMode: String) -> String {
|
|
441
|
+
switch transportMode {
|
|
442
|
+
case "walking":
|
|
443
|
+
return "pedestrian"
|
|
444
|
+
case "transit":
|
|
445
|
+
return "ctx"
|
|
446
|
+
default:
|
|
447
|
+
return "car"
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
303
451
|
private func launchCabify(
|
|
304
452
|
destination: CLLocationCoordinate2D,
|
|
305
453
|
start: CLLocationCoordinate2D?,
|
|
@@ -342,6 +490,66 @@ import MapKit
|
|
|
342
490
|
openURL(urlString, completion: completion)
|
|
343
491
|
}
|
|
344
492
|
|
|
493
|
+
private func shareToTesla(
|
|
494
|
+
destination: CLLocationCoordinate2D,
|
|
495
|
+
destinationName: String?,
|
|
496
|
+
viewController: UIViewController?,
|
|
497
|
+
completion: @escaping (Bool, String?) -> Void
|
|
498
|
+
) {
|
|
499
|
+
guard let viewController = viewController else {
|
|
500
|
+
completion(false, "Unable to present share sheet")
|
|
501
|
+
return
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
let activityViewController = UIActivityViewController(
|
|
505
|
+
activityItems: [teslaShareText(destination: destination, destinationName: destinationName)],
|
|
506
|
+
applicationActivities: nil
|
|
507
|
+
)
|
|
508
|
+
activityViewController.popoverPresentationController?.sourceView = viewController.view
|
|
509
|
+
activityViewController.completionWithItemsHandler = { _, completed, _, error in
|
|
510
|
+
if let error = error {
|
|
511
|
+
completion(false, error.localizedDescription)
|
|
512
|
+
} else if completed {
|
|
513
|
+
completion(true, nil)
|
|
514
|
+
} else {
|
|
515
|
+
completion(false, "Share cancelled")
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
viewController.present(activityViewController, animated: true)
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
func teslaShareText(destination: CLLocationCoordinate2D, destinationName: String?) -> String {
|
|
523
|
+
"\(teslaShareLabel(destinationName))\n\n\(googleMapsPositionURLString(destination: destination))"
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
func googleMapsPositionURLString(destination: CLLocationCoordinate2D) -> String {
|
|
527
|
+
let coordinates = String(
|
|
528
|
+
format: "%.6f,%.6f",
|
|
529
|
+
locale: Locale(identifier: "en_US_POSIX"),
|
|
530
|
+
destination.latitude,
|
|
531
|
+
destination.longitude
|
|
532
|
+
)
|
|
533
|
+
return "https://maps.google.com/?q=\(coordinates)"
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
private func teslaShareLabel(_ destinationName: String?) -> String {
|
|
537
|
+
guard let destinationName = destinationName else {
|
|
538
|
+
return "Dropped pin"
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
let normalizedName = destinationName
|
|
542
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
543
|
+
.replacingOccurrences(of: "[\\r\\n]+", with: " ", options: .regularExpression)
|
|
544
|
+
return normalizedName.isEmpty ? "Dropped pin" : normalizedName
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
private func encoded(_ value: String) -> String {
|
|
548
|
+
var allowed = CharacterSet.urlQueryAllowed
|
|
549
|
+
allowed.remove(charactersIn: "&=+/?#")
|
|
550
|
+
return value.addingPercentEncoding(withAllowedCharacters: allowed) ?? value
|
|
551
|
+
}
|
|
552
|
+
|
|
345
553
|
private func openURL(_ urlString: String, completion: @escaping (Bool, String?) -> Void) {
|
|
346
554
|
guard let url = URL(string: urlString) else {
|
|
347
555
|
completion(false, "Invalid URL")
|
|
@@ -392,3 +600,4 @@ import MapKit
|
|
|
392
600
|
return Array(navigationApps.keys)
|
|
393
601
|
}
|
|
394
602
|
}
|
|
603
|
+
// swiftlint:enable type_body_length
|