@capgo/capacitor-launch-navigator 8.0.20 → 8.0.21

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.
@@ -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
- private let navigationApps: [String: (name: String, urlScheme: String)] = [
8
- "apple_maps": ("Apple Maps", "maps://"),
9
- "google_maps": ("Google Maps", "comgooglemaps://"),
10
- "waze": ("Waze", "waze://"),
11
- "citymapper": ("Citymapper", "citymapper://"),
12
- "garmin_navigon": ("Garmin Navigon", "navigon://"),
13
- "transit_app": ("Transit App", "transit://"),
14
- "yandex": ("Yandex Navigator", "yandexnavi://"),
15
- "uber": ("Uber", "uber://"),
16
- "tomtom": ("TomTom", "tomtomgo://"),
17
- "sygic": ("Sygic", "com.sygic.aura://"),
18
- "here": ("HERE Maps", "here-route://"),
19
- "moovit": ("Moovit", "moovit://"),
20
- "lyft": ("Lyft", "lyft://"),
21
- "mapsme": ("MAPS.ME", "mapsme://"),
22
- "cabify": ("Cabify", "cabify://"),
23
- "baidu": ("Baidu Maps", "baidumap://"),
24
- "gaode": ("Gaode Maps", "iosamap://"),
25
- "99taxi": ("99 Taxi", "99app://")
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,14 @@ import MapKit
124
168
  start: start,
125
169
  completion: completion
126
170
  )
171
+ case "tesla":
172
+ shareToTesla(
173
+ destination: destination,
174
+ start: start,
175
+ transportMode: transportMode,
176
+ viewController: viewController,
177
+ completion: completion
178
+ )
127
179
  default:
128
180
  completion(false, "Unsupported navigation app: \(app)")
129
181
  }
@@ -300,6 +352,103 @@ import MapKit
300
352
  openURL(urlString, completion: completion)
301
353
  }
302
354
 
355
+ private func launchGuruMaps(
356
+ destination: CLLocationCoordinate2D,
357
+ start: CLLocationCoordinate2D?,
358
+ transportMode: String,
359
+ completion: @escaping (Bool, String?) -> Void
360
+ ) {
361
+ var urlString = "guru://nav?finish=\(destination.latitude),\(destination.longitude)&mode=\(guruMapsMode(transportMode))&start_navigation=true"
362
+
363
+ if let startCoord = start {
364
+ urlString += "&start=\(startCoord.latitude),\(startCoord.longitude)"
365
+ }
366
+
367
+ openURL(urlString, completion: completion)
368
+ }
369
+
370
+ private func guruMapsMode(_ transportMode: String) -> String {
371
+ switch transportMode {
372
+ case "walking":
373
+ return "pedestrian"
374
+ case "bicycling":
375
+ return "bicycle"
376
+ default:
377
+ return "auto"
378
+ }
379
+ }
380
+
381
+ private func launchOrganicMaps(
382
+ destination: CLLocationCoordinate2D,
383
+ start: CLLocationCoordinate2D?,
384
+ destinationName: String?,
385
+ transportMode: String,
386
+ completion: @escaping (Bool, String?) -> Void
387
+ ) {
388
+ let origin = start.map { "\($0.latitude),\($0.longitude)" } ?? "currentLocation"
389
+ var urlString = "om://v2/nav?origin=\(encoded(origin))&destination=\(destination.latitude),\(destination.longitude)&mode=\(organicMapsMode(transportMode))"
390
+
391
+ if let destinationName = destinationName, !destinationName.isEmpty {
392
+ urlString += "&destination_name=\(encoded(destinationName))"
393
+ }
394
+
395
+ openURL(urlString, completion: completion)
396
+ }
397
+
398
+ private func organicMapsMode(_ transportMode: String) -> String {
399
+ switch transportMode {
400
+ case "walking":
401
+ return "pedestrian"
402
+ case "bicycling":
403
+ return "bicycle"
404
+ case "transit":
405
+ return "transit"
406
+ default:
407
+ return "drive"
408
+ }
409
+ }
410
+
411
+ private func launchYandexMaps(
412
+ destination: CLLocationCoordinate2D,
413
+ start: CLLocationCoordinate2D?,
414
+ completion: @escaping (Bool, String?) -> Void
415
+ ) {
416
+ var urlString = "yandexmaps://build_route_on_map/?lat_to=\(destination.latitude)&lon_to=\(destination.longitude)"
417
+
418
+ if let startCoord = start {
419
+ urlString += "&lat_from=\(startCoord.latitude)&lon_from=\(startCoord.longitude)"
420
+ }
421
+
422
+ openURL(urlString, completion: completion)
423
+ }
424
+
425
+ private func launch2Gis(
426
+ destination: CLLocationCoordinate2D,
427
+ start: CLLocationCoordinate2D?,
428
+ transportMode: String,
429
+ completion: @escaping (Bool, String?) -> Void
430
+ ) {
431
+ var urlString = "dgis://2gis.ru/routeSearch/rsType/\(twoGisMode(transportMode))"
432
+
433
+ if let startCoord = start {
434
+ urlString += "/from/\(startCoord.longitude),\(startCoord.latitude)"
435
+ }
436
+
437
+ urlString += "/to/\(destination.longitude),\(destination.latitude)"
438
+ openURL(urlString, completion: completion)
439
+ }
440
+
441
+ private func twoGisMode(_ transportMode: String) -> String {
442
+ switch transportMode {
443
+ case "walking":
444
+ return "pedestrian"
445
+ case "transit":
446
+ return "ctx"
447
+ default:
448
+ return "car"
449
+ }
450
+ }
451
+
303
452
  private func launchCabify(
304
453
  destination: CLLocationCoordinate2D,
305
454
  start: CLLocationCoordinate2D?,
@@ -342,6 +491,71 @@ import MapKit
342
491
  openURL(urlString, completion: completion)
343
492
  }
344
493
 
494
+ private func shareToTesla(
495
+ destination: CLLocationCoordinate2D,
496
+ start: CLLocationCoordinate2D?,
497
+ transportMode: String,
498
+ viewController: UIViewController?,
499
+ completion: @escaping (Bool, String?) -> Void
500
+ ) {
501
+ guard let viewController = viewController else {
502
+ completion(false, "Unable to present share sheet")
503
+ return
504
+ }
505
+
506
+ guard let url = googleMapsWebURL(destination: destination, start: start, transportMode: transportMode) else {
507
+ completion(false, "Invalid Tesla share URL")
508
+ return
509
+ }
510
+
511
+ let activityViewController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
512
+ activityViewController.popoverPresentationController?.sourceView = viewController.view
513
+ activityViewController.completionWithItemsHandler = { _, completed, _, error in
514
+ if let error = error {
515
+ completion(false, error.localizedDescription)
516
+ } else if completed {
517
+ completion(true, nil)
518
+ } else {
519
+ completion(false, "Share cancelled")
520
+ }
521
+ }
522
+
523
+ viewController.present(activityViewController, animated: true)
524
+ }
525
+
526
+ private func googleMapsWebURL(
527
+ destination: CLLocationCoordinate2D,
528
+ start: CLLocationCoordinate2D?,
529
+ transportMode: String
530
+ ) -> URL? {
531
+ var urlString = "https://www.google.com/maps/dir/?api=1&destination=\(destination.latitude),\(destination.longitude)&travelmode=\(googleMapsTravelMode(transportMode))"
532
+
533
+ if let startCoord = start {
534
+ urlString += "&origin=\(startCoord.latitude),\(startCoord.longitude)"
535
+ }
536
+
537
+ return URL(string: urlString)
538
+ }
539
+
540
+ private func googleMapsTravelMode(_ transportMode: String) -> String {
541
+ switch transportMode {
542
+ case "walking":
543
+ return "walking"
544
+ case "bicycling":
545
+ return "bicycling"
546
+ case "transit":
547
+ return "transit"
548
+ default:
549
+ return "driving"
550
+ }
551
+ }
552
+
553
+ private func encoded(_ value: String) -> String {
554
+ var allowed = CharacterSet.urlQueryAllowed
555
+ allowed.remove(charactersIn: "&=+/?#")
556
+ return value.addingPercentEncoding(withAllowedCharacters: allowed) ?? value
557
+ }
558
+
345
559
  private func openURL(_ urlString: String, completion: @escaping (Bool, String?) -> Void) {
346
560
  guard let url = URL(string: urlString) else {
347
561
  completion(false, "Invalid URL")
@@ -392,3 +606,4 @@ import MapKit
392
606
  return Array(navigationApps.keys)
393
607
  }
394
608
  }
609
+ // swiftlint:enable type_body_length