capacitor-google-navigation 0.0.3 → 0.0.5

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 CHANGED
@@ -134,8 +134,8 @@ startNavigation({ lat, lng, travelMode })
134
134
  ↓ fires onRouteChanged on recalculation
135
135
  stopNavigation()
136
136
  ↓ ends guidance, clears destination
137
- showNavigationView({ show: false })
138
- ↓ dismisses native map, restores app UI
137
+ showNavigationView({ show: false }) — or user taps the ✕ close button
138
+ ↓ dismisses native map, fires onNavigationClosed, restores app UI
139
139
  ```
140
140
 
141
141
  ---
@@ -154,9 +154,10 @@ interface UseNavigationOptions {
154
154
  apiKey: string;
155
155
  onArrival?: (event: any) => void;
156
156
  onRouteChanged?: () => void;
157
+ onNavigationClosed?: () => void;
157
158
  }
158
159
 
159
- export function useGoogleNavigation({ apiKey, onArrival, onRouteChanged }: UseNavigationOptions) {
160
+ export function useGoogleNavigation({ apiKey, onArrival, onRouteChanged, onNavigationClosed }: UseNavigationOptions) {
160
161
  const listeners = useRef<PluginListenerHandle[]>([]);
161
162
 
162
163
  useEffect(() => {
@@ -176,6 +177,11 @@ export function useGoogleNavigation({ apiKey, onArrival, onRouteChanged }: UseNa
176
177
  listeners.current.push(h);
177
178
  }
178
179
 
180
+ if (onNavigationClosed) {
181
+ const h = await GoogleNavigation.addListener('onNavigationClosed', onNavigationClosed);
182
+ listeners.current.push(h);
183
+ }
184
+
179
185
  await GoogleNavigation.initialize({ apiKey });
180
186
  };
181
187
 
@@ -232,6 +238,7 @@ const NavigationPage: React.FC = () => {
232
238
  apiKey: import.meta.env.VITE_GOOGLE_NAV_API_KEY as string,
233
239
  onArrival: () => setShowArrival(true),
234
240
  onRouteChanged: () => console.log('Route recalculated'),
241
+ onNavigationClosed: () => console.log('User closed navigation'),
235
242
  });
236
243
 
237
244
  return (
@@ -301,6 +308,11 @@ const routeHandle = await GoogleNavigation.addListener('onRouteChanged', () => {
301
308
  console.log('Route recalculated');
302
309
  });
303
310
 
311
+ const closedHandle = await GoogleNavigation.addListener('onNavigationClosed', () => {
312
+ // Fired when the user taps the ✕ close button on the native navigation view
313
+ console.log('Navigation closed by user');
314
+ });
315
+
304
316
  // 2. Initialize the SDK (fires onNavigationReady when done)
305
317
  await GoogleNavigation.initialize({ apiKey: 'YOUR_API_KEY' });
306
318
 
@@ -400,14 +412,14 @@ Show/hide navigation view
400
412
  ### addListener(...)
401
413
 
402
414
  ```typescript
403
- addListener(eventName: 'onArrival' | 'onRouteChanged' | 'onNavigationReady', listenerFunc: (event: any) => void) => Promise<PluginListenerHandle>
415
+ addListener(eventName: 'onArrival' | 'onRouteChanged' | 'onNavigationReady' | 'onNavigationClosed', listenerFunc: (event: any) => void) => Promise<PluginListenerHandle>
404
416
  ```
405
417
 
406
418
  Add listener for navigation events
407
419
 
408
420
  | Param | Type |
409
421
  | ------------------ | ----------------------------------------------------------------- |
410
- | **`eventName`** | <code>'onArrival' \| 'onRouteChanged' \| 'onNavigationReady'</code> |
422
+ | **`eventName`** | <code>'onArrival' \| 'onRouteChanged' \| 'onNavigationReady' \| 'onNavigationClosed'</code> |
411
423
  | **`listenerFunc`** | <code>(event: any) =&gt; void</code> |
412
424
 
413
425
  **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
@@ -446,6 +458,7 @@ Remove all listeners
446
458
  | `onNavigationReady` | `{}` | SDK has initialized and the navigator is available |
447
459
  | `onArrival` | `{ latitude, longitude, title }` | User arrives at the destination waypoint |
448
460
  | `onRouteChanged` | `{}` | The route is recalculated (traffic, missed turn, etc.) |
461
+ | `onNavigationClosed` | `{}` | User tapped the ✕ close button on the native navigation view (iOS) |
449
462
 
450
463
  ---
451
464
 
@@ -118,6 +118,10 @@ public class GoogleNavigation {
118
118
  }
119
119
 
120
120
  NavigationFragment fragment = NavigationFragment.newInstance();
121
+ fragment.setOnCloseListener(() -> {
122
+ fm.beginTransaction().remove(fragment).commitAllowingStateLoss();
123
+ plugin.fireEvent("onNavigationClosed", new JSObject());
124
+ });
121
125
  fm.beginTransaction()
122
126
  .add(android.R.id.content, fragment, FRAGMENT_TAG)
123
127
  .commitAllowingStateLoss();
@@ -1,9 +1,15 @@
1
1
  package com.attributeai.navigation;
2
2
 
3
+ import android.graphics.Color;
4
+ import android.graphics.Typeface;
3
5
  import android.os.Bundle;
6
+ import android.util.TypedValue;
7
+ import android.view.Gravity;
4
8
  import android.view.LayoutInflater;
5
9
  import android.view.View;
6
10
  import android.view.ViewGroup;
11
+ import android.widget.Button;
12
+ import android.widget.FrameLayout;
7
13
 
8
14
  import androidx.annotation.NonNull;
9
15
  import androidx.annotation.Nullable;
@@ -19,11 +25,16 @@ import com.google.android.libraries.navigation.NavigationView;
19
25
  public class NavigationFragment extends Fragment {
20
26
 
21
27
  private NavigationView navigationView;
28
+ private Runnable onCloseListener;
22
29
 
23
30
  public static NavigationFragment newInstance() {
24
31
  return new NavigationFragment();
25
32
  }
26
33
 
34
+ public void setOnCloseListener(Runnable listener) {
35
+ this.onCloseListener = listener;
36
+ }
37
+
27
38
  @Nullable
28
39
  @Override
29
40
  public View onCreateView(
@@ -33,7 +44,37 @@ public class NavigationFragment extends Fragment {
33
44
  ) {
34
45
  navigationView = new NavigationView(requireContext());
35
46
  navigationView.onCreate(savedInstanceState);
36
- return navigationView;
47
+
48
+ FrameLayout root = new FrameLayout(requireContext());
49
+ root.addView(navigationView, new FrameLayout.LayoutParams(
50
+ FrameLayout.LayoutParams.MATCH_PARENT,
51
+ FrameLayout.LayoutParams.MATCH_PARENT
52
+ ));
53
+
54
+ Button closeButton = new Button(requireContext());
55
+ closeButton.setText("✕");
56
+ closeButton.setTextColor(Color.WHITE);
57
+ closeButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
58
+ closeButton.setTypeface(null, Typeface.BOLD);
59
+ closeButton.setBackgroundColor(Color.argb(153, 0, 0, 0)); // 60% black
60
+ closeButton.setOnClickListener(v -> {
61
+ if (onCloseListener != null) onCloseListener.run();
62
+ });
63
+
64
+ int sizePx = (int) TypedValue.applyDimension(
65
+ TypedValue.COMPLEX_UNIT_DIP, 40, getResources().getDisplayMetrics()
66
+ );
67
+ int marginPx = (int) TypedValue.applyDimension(
68
+ TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()
69
+ );
70
+
71
+ FrameLayout.LayoutParams btnParams = new FrameLayout.LayoutParams(sizePx, sizePx);
72
+ btnParams.gravity = Gravity.TOP | Gravity.START;
73
+ btnParams.topMargin = marginPx;
74
+ btnParams.leftMargin = marginPx;
75
+ root.addView(closeButton, btnParams);
76
+
77
+ return root;
37
78
  }
38
79
 
39
80
  @Override
@@ -49,6 +49,14 @@ import GoogleNavigation
49
49
 
50
50
  let mapVC = NavigationMapViewController(session: session)
51
51
  mapVC.modalPresentationStyle = .fullScreen
52
+ mapVC.onDismiss = { [weak self] in
53
+ guard let self = self else { return }
54
+ self.navigationSession?.navigator?.remove(self)
55
+ self.navigationSession?.isStarted = false
56
+ self.navigationSession = nil
57
+ self.mapViewController = nil
58
+ self.plugin?.notifyListeners("onNavigationClosed", data: [:])
59
+ }
52
60
  self.mapViewController = mapVC
53
61
 
54
62
  presentingVC.present(mapVC, animated: true) {
@@ -101,7 +109,19 @@ import GoogleNavigation
101
109
  self?.mapViewController?.setCameraFollowing()
102
110
  completion(true, nil)
103
111
  } else {
104
- completion(false, "Route calculation failed: \(routeStatus.rawValue)")
112
+ let reason: String
113
+ switch routeStatus {
114
+ case .apiKeyNotAuthorized: reason = "API key not authorized for Navigation SDK"
115
+ case .networkError: reason = "Network error — check internet connection"
116
+ case .noRouteFound: reason = "No route found to destination"
117
+ case .locationUnavailable: reason = "Location unavailable — check permissions"
118
+ case .quotaExceeded: reason = "API quota exceeded"
119
+ case .waypointError: reason = "Invalid waypoint coordinates"
120
+ case .travelModeUnsupported: reason = "Travel mode not supported"
121
+ case .canceled: reason = "Route request was canceled"
122
+ default: reason = "Unknown error (code \(routeStatus.rawValue))"
123
+ }
124
+ completion(false, "Route calculation failed: \(reason)")
105
125
  }
106
126
  }
107
127
  }
@@ -5,6 +5,7 @@ import GoogleNavigation
5
5
  class NavigationMapViewController: UIViewController {
6
6
  private let session: GMSNavigationSession
7
7
  private var mapView: GMSMapView?
8
+ var onDismiss: (() -> Void)?
8
9
 
9
10
  init(session: GMSNavigationSession) {
10
11
  self.session = session
@@ -15,18 +16,48 @@ class NavigationMapViewController: UIViewController {
15
16
  fatalError("init(coder:) not supported")
16
17
  }
17
18
 
18
- override func viewDidLoad() {
19
- super.viewDidLoad()
20
-
19
+ override func loadView() {
21
20
  let options = GMSMapViewOptions()
22
- options.frame = view.bounds
21
+ options.frame = UIScreen.main.bounds
23
22
  let mapView = GMSMapView(options: options)
24
- mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
25
- view.addSubview(mapView)
26
23
  self.mapView = mapView
24
+ self.view = mapView
25
+ }
26
+
27
+ override func viewDidLoad() {
28
+ super.viewDidLoad()
29
+
30
+ guard let mapView = mapView else { return }
31
+ let enabled = mapView.enableNavigation(with: session)
32
+ if enabled {
33
+ mapView.cameraMode = .following
34
+ }
35
+
36
+ addCloseButton()
37
+ }
38
+
39
+ private func addCloseButton() {
40
+ let button = UIButton(type: .system)
41
+ button.setImage(UIImage(systemName: "xmark"), for: .normal)
42
+ button.tintColor = .white
43
+ button.backgroundColor = UIColor.black.withAlphaComponent(0.6)
44
+ button.layer.cornerRadius = 20
45
+ button.translatesAutoresizingMaskIntoConstraints = false
46
+ button.addTarget(self, action: #selector(closeTapped), for: .touchUpInside)
47
+ view.addSubview(button)
48
+
49
+ NSLayoutConstraint.activate([
50
+ button.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16),
51
+ button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
52
+ button.widthAnchor.constraint(equalToConstant: 40),
53
+ button.heightAnchor.constraint(equalToConstant: 40)
54
+ ])
55
+ }
27
56
 
28
- _ = mapView.enableNavigation(with: session)
29
- mapView.cameraMode = .following
57
+ @objc private func closeTapped() {
58
+ dismiss(animated: true) { [weak self] in
59
+ self?.onDismiss?()
60
+ }
30
61
  }
31
62
 
32
63
  func setCameraFollowing() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-google-navigation",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Google maps turn by turn navigation for capcitor",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",