@capacitor/app 8.1.0 → 8.1.1-dev-2542-20260611T172948.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/Package.swift CHANGED
@@ -10,14 +10,13 @@ let package = Package(
10
10
  targets: ["AppPlugin"])
11
11
  ],
12
12
  dependencies: [
13
- .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0")
13
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "9.0.0-alpha.0")
14
14
  ],
15
15
  targets: [
16
16
  .target(
17
17
  name: "AppPlugin",
18
18
  dependencies: [
19
- .product(name: "Capacitor", package: "capacitor-swift-pm"),
20
- .product(name: "Cordova", package: "capacitor-swift-pm")
19
+ .product(name: "Capacitor", package: "capacitor-swift-pm")
21
20
  ],
22
21
  path: "ios/Sources/AppPlugin"),
23
22
  .testTarget(
package/README.md CHANGED
@@ -43,6 +43,9 @@ For being able to open the app from a custom scheme you need to register the sch
43
43
 
44
44
  `custom_url_scheme` value is stored in `strings.xml`. When the Android platform is added, `@capacitor/cli` adds the app's package name as default value, but can be replaced by editing the `strings.xml` file.
45
45
 
46
+ ## Android Predictive Back
47
+ Android predictive back also requires `android:enableOnBackInvokedCallback="true"` on `<application>` in your `AndroidManifest.xml` (on Android 14; default on Android 15+).
48
+
46
49
  ## Example
47
50
 
48
51
  ```typescript
@@ -72,9 +75,10 @@ const checkAppLaunchUrl = async () => {
72
75
  <docgen-config>
73
76
  <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
74
77
 
75
- | Prop | Type | Description | Default | Since |
76
- | ------------------------------ | -------------------- | ------------------------------------------------------------------------------ | ------------------ | ----- |
77
- | **`disableBackButtonHandler`** | <code>boolean</code> | Disable the plugin's default back button handling. Only available for Android. | <code>false</code> | 7.1.0 |
78
+ | Prop | Type | Description | Default | Since |
79
+ | ------------------------------ | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
80
+ | **`disableBackButtonHandler`** | <code>boolean</code> | Disable the plugin's default back button handling. Only available for Android. | <code>false</code> | 7.1.0 |
81
+ | **`enableEdgeGestureHandler`** | <code>boolean</code> | Enable the plugin's edge gesture handler at startup. When enabled, the plugin emits `edgeGesture` events for system edge swipes (iOS left/right screen-edge pans, Android predictive back). On Android, enabling this handler suppresses the default `backButton` handler for the duration that the edge gesture handler is active. The Android predictive-back integration requires API 34 (Android 14) or later; on earlier versions the configuration is accepted but no events will be emitted. Android predictive back also requires `android:enableOnBackInvokedCallback="true"` on `&lt;application&gt;` in your `AndroidManifest.xml` (on Android 14; default on Android 15+). | <code>false</code> | 9.0.0 |
78
82
 
79
83
  ### Examples
80
84
 
@@ -84,7 +88,8 @@ In `capacitor.config.json`:
84
88
  {
85
89
  "plugins": {
86
90
  "App": {
87
- "disableBackButtonHandler": true
91
+ "disableBackButtonHandler": true,
92
+ "enableEdgeGestureHandler": true
88
93
  }
89
94
  }
90
95
  }
@@ -101,6 +106,7 @@ const config: CapacitorConfig = {
101
106
  plugins: {
102
107
  App: {
103
108
  disableBackButtonHandler: true,
109
+ enableEdgeGestureHandler: true,
104
110
  },
105
111
  },
106
112
  };
@@ -121,12 +127,14 @@ export default config;
121
127
  * [`minimizeApp()`](#minimizeapp)
122
128
  * [`getAppLanguage()`](#getapplanguage)
123
129
  * [`toggleBackButtonHandler(...)`](#togglebackbuttonhandler)
130
+ * [`toggleEdgeGestureHandler(...)`](#toggleedgegesturehandler)
124
131
  * [`addListener('appStateChange', ...)`](#addlistenerappstatechange-)
125
132
  * [`addListener('pause', ...)`](#addlistenerpause-)
126
133
  * [`addListener('resume', ...)`](#addlistenerresume-)
127
134
  * [`addListener('appUrlOpen', ...)`](#addlistenerappurlopen-)
128
135
  * [`addListener('appRestoredResult', ...)`](#addlistenerapprestoredresult-)
129
136
  * [`addListener('backButton', ...)`](#addlistenerbackbutton-)
137
+ * [`addListener('edgeGesture', ...)`](#addlisteneredgegesture-)
130
138
  * [`removeAllListeners()`](#removealllisteners)
131
139
  * [Interfaces](#interfaces)
132
140
  * [Type Aliases](#type-aliases)
@@ -246,6 +254,36 @@ Only available for Android.
246
254
  --------------------
247
255
 
248
256
 
257
+ ### toggleEdgeGestureHandler(...)
258
+
259
+ ```typescript
260
+ toggleEdgeGestureHandler(options: ToggleEdgeGestureHandlerOptions) => Promise<void>
261
+ ```
262
+
263
+ Enables or disables the plugin's edge gesture handling at runtime.
264
+
265
+ When enabled, the plugin installs platform edge-gesture recognizers
266
+ and begins emitting `edgeGesture` events. When disabled, the
267
+ recognizers are removed and no further events are emitted.
268
+
269
+ On Android, enabling the edge gesture handler temporarily disables
270
+ the default `backButton` handler; disabling it restores the previous
271
+ back button handler state. The Android predictive-back integration
272
+ requires API 34 (Android 14) or later; on earlier versions the call
273
+ resolves but no events will be emitted. Android predictive back also
274
+ requires `android:enableOnBackInvokedCallback="true"` on
275
+ `&lt;application&gt;` in your `AndroidManifest.xml` (on Android 14; default
276
+ on Android 15+).
277
+
278
+ | Param | Type |
279
+ | ------------- | ------------------------------------------------------------------------------------------- |
280
+ | **`options`** | <code><a href="#toggleedgegesturehandleroptions">ToggleEdgeGestureHandlerOptions</a></code> |
281
+
282
+ **Since:** 9.0.0
283
+
284
+ --------------------
285
+
286
+
249
287
  ### addListener('appStateChange', ...)
250
288
 
251
289
  ```typescript
@@ -403,6 +441,38 @@ If you want to close the app, call `App.exitApp()`.
403
441
  --------------------
404
442
 
405
443
 
444
+ ### addListener('edgeGesture', ...)
445
+
446
+ ```typescript
447
+ addListener(eventName: 'edgeGesture', listenerFunc: EdgeGestureListener) => Promise<PluginListenerHandle>
448
+ ```
449
+
450
+ Listen for system edge-swipe gestures.
451
+
452
+ On iOS this fires for left- and right-edge screen pans tracked by
453
+ `UIScreenEdgePanGestureRecognizer`. On Android this fires for the
454
+ predictive back gesture (requires Android 14 / API 34 or later).
455
+
456
+ The edge gesture handler must be active for events to fire; enable
457
+ it via the `enableEdgeGestureHandler` configuration option or at
458
+ runtime via `toggleEdgeGestureHandler({ enabled: true })`.
459
+
460
+ Each gesture produces a sequence of events: a single `start`, zero
461
+ or more `progress`, and then either `commit` (the gesture completed)
462
+ or `cancel` (the gesture was abandoned).
463
+
464
+ | Param | Type |
465
+ | ------------------ | ------------------------------------------------------------------- |
466
+ | **`eventName`** | <code>'edgeGesture'</code> |
467
+ | **`listenerFunc`** | <code><a href="#edgegesturelistener">EdgeGestureListener</a></code> |
468
+
469
+ **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
470
+
471
+ **Since:** 9.0.0
472
+
473
+ --------------------
474
+
475
+
406
476
  ### removeAllListeners()
407
477
 
408
478
  ```typescript
@@ -457,6 +527,13 @@ Remove all native listeners for this plugin
457
527
  | **`enabled`** | <code>boolean</code> | Indicates whether to enable or disable default back button handling. | 7.1.0 |
458
528
 
459
529
 
530
+ #### ToggleEdgeGestureHandlerOptions
531
+
532
+ | Prop | Type | Description | Since |
533
+ | ------------- | -------------------- | ---------------------------------------------------------------- | ----- |
534
+ | **`enabled`** | <code>boolean</code> | Whether to enable or disable the plugin's edge gesture handling. | 9.0.0 |
535
+
536
+
460
537
  #### PluginListenerHandle
461
538
 
462
539
  | Prop | Type |
@@ -491,6 +568,17 @@ Remove all native listeners for this plugin
491
568
  | **`canGoBack`** | <code>boolean</code> | Indicates whether the browser can go back in history. False when the history stack is on the first entry. | 1.0.0 |
492
569
 
493
570
 
571
+ #### EdgeGestureListenerEvent
572
+
573
+ | Prop | Type | Description | Since |
574
+ | --------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----- |
575
+ | **`phase`** | <code>'start' \| 'progress' \| 'cancel' \| 'commit'</code> | The current phase of the edge gesture. - `start`: the user has initiated an edge swipe. - `progress`: the user is moving their finger; emitted continuously during the gesture. - `commit`: the user released the gesture and the system accepted it (for example, a back navigation should occur). - `cancel`: the user released the gesture without committing it, or the system cancelled it. | 9.0.0 |
576
+ | **`progress`** | <code>number</code> | How far the gesture has progressed, normalized between `0` and `1`. On `start` this is the initial progress reported by the system. On `progress` it updates as the user drags. On `commit` and `cancel` it reports the last observed progress value. | 9.0.0 |
577
+ | **`swipeEdge`** | <code>'none' \| 'left' \| 'right'</code> | Which screen edge the gesture originated from. On iOS this is `'left'` or `'right'` (left/right screen-edge pans are tracked). On Android this reflects the value reported by the predictive-back system and may also be `'none'` when the platform does not report a specific edge. | 9.0.0 |
578
+ | **`touchX`** | <code>number</code> | X coordinate of the touch that initiated or is driving the gesture. On iOS the value is in points relative to the WebView. On Android the value is provided by the platform's `BackEvent.getTouchX()`. | 9.0.0 |
579
+ | **`touchY`** | <code>number</code> | Y coordinate of the touch that initiated or is driving the gesture. On iOS the value is in points relative to the WebView. On Android the value is provided by the platform's `BackEvent.getTouchY()`. | 9.0.0 |
580
+
581
+
494
582
  ### Type Aliases
495
583
 
496
584
 
@@ -513,4 +601,9 @@ Remove all native listeners for this plugin
513
601
 
514
602
  <code>(event: <a href="#backbuttonlistenerevent">BackButtonListenerEvent</a>): void</code>
515
603
 
604
+
605
+ #### EdgeGestureListener
606
+
607
+ <code>(event: <a href="#edgegesturelistenerevent">EdgeGestureListenerEvent</a>): void</code>
608
+
516
609
  </docgen-api>
@@ -1,10 +1,19 @@
1
1
  package com.capacitorjs.plugins.app;
2
2
 
3
+ import static android.window.BackEvent.EDGE_LEFT;
4
+ import static android.window.BackEvent.EDGE_NONE;
5
+ import static android.window.BackEvent.EDGE_RIGHT;
6
+
3
7
  import android.content.Intent;
4
8
  import android.content.pm.ApplicationInfo;
5
9
  import android.content.pm.PackageInfo;
6
10
  import android.net.Uri;
11
+ import android.os.Build;
12
+ import android.window.BackEvent;
13
+ import android.window.OnBackAnimationCallback;
14
+ import android.window.OnBackInvokedDispatcher;
7
15
  import androidx.activity.OnBackPressedCallback;
16
+ import androidx.annotation.NonNull;
8
17
  import androidx.appcompat.app.AppCompatDelegate;
9
18
  import androidx.core.content.pm.PackageInfoCompat;
10
19
  import androidx.core.os.LocaleListCompat;
@@ -21,33 +30,40 @@ import java.util.Locale;
21
30
  public class AppPlugin extends Plugin {
22
31
 
23
32
  private static final String EVENT_BACK_BUTTON = "backButton";
33
+ private static final String EVENT_BACK_GESTURE = "edgeGesture";
24
34
  private static final String EVENT_URL_OPEN = "appUrlOpen";
25
35
  private static final String EVENT_STATE_CHANGE = "appStateChange";
26
36
  private static final String EVENT_RESTORED_RESULT = "appRestoredResult";
27
37
  private static final String EVENT_PAUSE = "pause";
28
38
  private static final String EVENT_RESUME = "resume";
29
39
  private boolean hasPausedEver = false;
40
+ private boolean backButtonHandlerEnabled = false;
41
+ private boolean edgeGestureHandlerEnabled = false;
30
42
 
31
43
  private OnBackPressedCallback onBackPressedCallback;
44
+ private OnBackAnimationCallback onBackAnimationCallback;
45
+
46
+ private String activeEdge = null;
47
+ private Float lastEdgeProgress = null;
48
+ private Float lastEdgeTouchX = null;
49
+ private Float lastEdgeTouchY = null;
32
50
 
33
51
  public void load() {
34
- boolean disableBackButtonHandler = getConfig().getBoolean("disableBackButtonHandler", false);
35
-
36
- bridge
37
- .getApp()
38
- .setStatusChangeListener((isActive) -> {
39
- Logger.debug(getLogTag(), "Firing change: " + isActive);
40
- JSObject data = new JSObject();
41
- data.put("isActive", isActive);
42
- notifyListeners(EVENT_STATE_CHANGE, data, false);
43
- });
44
- bridge
45
- .getApp()
46
- .setAppRestoredListener((result) -> {
47
- Logger.debug(getLogTag(), "Firing restored result");
48
- notifyListeners(EVENT_RESTORED_RESULT, result.getWrappedResult(), true);
49
- });
50
- this.onBackPressedCallback = new OnBackPressedCallback(!disableBackButtonHandler) {
52
+ this.backButtonHandlerEnabled = !getConfig().getBoolean("disableBackButtonHandler", false);
53
+ this.edgeGestureHandlerEnabled = getConfig().getBoolean("enableEdgeGestureHandler", false);
54
+
55
+ bridge.getApp().setStatusChangeListener((isActive) -> {
56
+ Logger.debug(getLogTag(), "Firing change: " + isActive);
57
+ JSObject data = new JSObject();
58
+ data.put("isActive", isActive);
59
+ notifyListeners(EVENT_STATE_CHANGE, data, false);
60
+ });
61
+ bridge.getApp().setAppRestoredListener((result) -> {
62
+ Logger.debug(getLogTag(), "Firing restored result");
63
+ notifyListeners(EVENT_RESTORED_RESULT, result.getWrappedResult(), true);
64
+ });
65
+
66
+ this.onBackPressedCallback = new OnBackPressedCallback(false) {
51
67
  @Override
52
68
  public void handleOnBackPressed() {
53
69
  if (!hasListeners(EVENT_BACK_BUTTON)) {
@@ -64,6 +80,12 @@ public class AppPlugin extends Plugin {
64
80
  };
65
81
 
66
82
  getActivity().getOnBackPressedDispatcher().addCallback(getActivity(), this.onBackPressedCallback);
83
+
84
+ if (this.edgeGestureHandlerEnabled) {
85
+ this.setupBackGestureHandlers();
86
+ }
87
+
88
+ applyBackButtonHandlerState();
67
89
  }
68
90
 
69
91
  @PluginMethod
@@ -116,6 +138,15 @@ public class AppPlugin extends Plugin {
116
138
  call.resolve();
117
139
  }
118
140
 
141
+ @PluginMethod
142
+ public void getAppLanguage(PluginCall call) {
143
+ JSObject ret = new JSObject();
144
+ LocaleListCompat appLocales = AppCompatDelegate.getApplicationLocales();
145
+ Locale appLocale = !appLocales.isEmpty() ? appLocales.get(0) : null;
146
+ ret.put("value", appLocale != null ? appLocale.getLanguage() : Locale.getDefault().getLanguage());
147
+ call.resolve(ret);
148
+ }
149
+
119
150
  @PluginMethod
120
151
  public void toggleBackButtonHandler(PluginCall call) {
121
152
  if (this.onBackPressedCallback == null) {
@@ -123,19 +154,35 @@ public class AppPlugin extends Plugin {
123
154
  return;
124
155
  }
125
156
 
126
- Boolean enabled = call.getBoolean("enabled");
157
+ backButtonHandlerEnabled = call.getBoolean("enabled", false);
127
158
 
128
- this.onBackPressedCallback.setEnabled(enabled);
159
+ applyBackButtonHandlerState();
129
160
  call.resolve();
130
161
  }
131
162
 
132
163
  @PluginMethod
133
- public void getAppLanguage(PluginCall call) {
134
- JSObject ret = new JSObject();
135
- LocaleListCompat appLocales = AppCompatDelegate.getApplicationLocales();
136
- Locale appLocale = !appLocales.isEmpty() ? appLocales.get(0) : null;
137
- ret.put("value", appLocale != null ? appLocale.getLanguage() : Locale.getDefault().getLanguage());
138
- call.resolve(ret);
164
+ public void toggleEdgeGestureHandler(PluginCall call) {
165
+ if (getActivity() == null) {
166
+ call.reject("activity is null");
167
+ return;
168
+ }
169
+
170
+ edgeGestureHandlerEnabled = call.getBoolean("enabled", false);
171
+ applyBackButtonHandlerState();
172
+
173
+ if (edgeGestureHandlerEnabled) {
174
+ setupBackGestureHandlers();
175
+ } else {
176
+ teardownBackGestureHandlers();
177
+ }
178
+
179
+ call.resolve();
180
+ }
181
+
182
+ private void applyBackButtonHandlerState() {
183
+ if (this.onBackPressedCallback != null) {
184
+ this.onBackPressedCallback.setEnabled(backButtonHandlerEnabled && !edgeGestureHandlerEnabled);
185
+ }
139
186
  }
140
187
 
141
188
  /**
@@ -176,10 +223,120 @@ public class AppPlugin extends Plugin {
176
223
  @Override
177
224
  protected void handleOnDestroy() {
178
225
  unsetAppListeners();
226
+ teardownBackGestureHandlers();
179
227
  }
180
228
 
181
229
  private void unsetAppListeners() {
182
230
  bridge.getApp().setStatusChangeListener(null);
183
231
  bridge.getApp().setAppRestoredListener(null);
184
232
  }
233
+
234
+ private void setupBackGestureHandlers() {
235
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
236
+ if (this.onBackAnimationCallback != null) {
237
+ return;
238
+ }
239
+
240
+ this.onBackAnimationCallback = new OnBackAnimationCallback() {
241
+ @Override
242
+ public void onBackInvoked() {
243
+ if (hasListeners(EVENT_BACK_GESTURE)) {
244
+ JSObject data = new JSObject();
245
+ data.put("phase", "commit");
246
+ data.put("progress", lastEdgeProgress);
247
+ data.put("touchX", lastEdgeTouchX);
248
+ data.put("touchY", lastEdgeTouchY);
249
+ data.put("swipeEdge", activeEdge);
250
+
251
+ notifyListeners(EVENT_BACK_GESTURE, data, true);
252
+
253
+ lastEdgeProgress = null;
254
+ lastEdgeTouchX = null;
255
+ lastEdgeTouchY = null;
256
+ activeEdge = null;
257
+ }
258
+ }
259
+
260
+ @Override
261
+ public void onBackStarted(@NonNull BackEvent backEvent) {
262
+ if (hasListeners(EVENT_BACK_GESTURE)) {
263
+ JSObject data = new JSObject();
264
+ data.put("phase", "start");
265
+ data.put("progress", backEvent.getProgress());
266
+ data.put("touchX", backEvent.getTouchX());
267
+ data.put("touchY", backEvent.getTouchY());
268
+ data.put("swipeEdge", getSwipeEdge(backEvent.getSwipeEdge()));
269
+
270
+ notifyListeners(EVENT_BACK_GESTURE, data, true);
271
+
272
+ lastEdgeProgress = backEvent.getProgress();
273
+ lastEdgeTouchX = backEvent.getTouchX();
274
+ lastEdgeTouchY = backEvent.getTouchY();
275
+ activeEdge = getSwipeEdge(backEvent.getSwipeEdge());
276
+ }
277
+ }
278
+
279
+ @Override
280
+ public void onBackProgressed(@NonNull BackEvent backEvent) {
281
+ if (hasListeners(EVENT_BACK_GESTURE)) {
282
+ JSObject data = new JSObject();
283
+ data.put("phase", "progress");
284
+ data.put("progress", backEvent.getProgress());
285
+ data.put("touchX", backEvent.getTouchX());
286
+ data.put("touchY", backEvent.getTouchY());
287
+ data.put("swipeEdge", getSwipeEdge(backEvent.getSwipeEdge()));
288
+
289
+ notifyListeners(EVENT_BACK_GESTURE, data, true);
290
+
291
+ lastEdgeProgress = backEvent.getProgress();
292
+ lastEdgeTouchX = backEvent.getTouchX();
293
+ lastEdgeTouchY = backEvent.getTouchY();
294
+ activeEdge = getSwipeEdge(backEvent.getSwipeEdge());
295
+ }
296
+ }
297
+
298
+ @Override
299
+ public void onBackCancelled() {
300
+ if (hasListeners(EVENT_BACK_GESTURE)) {
301
+ JSObject data = new JSObject();
302
+ data.put("phase", "cancel");
303
+ data.put("progress", lastEdgeProgress);
304
+ data.put("touchX", lastEdgeTouchX);
305
+ data.put("touchY", lastEdgeTouchY);
306
+ data.put("swipeEdge", activeEdge);
307
+
308
+ notifyListeners(EVENT_BACK_GESTURE, data, true);
309
+
310
+ lastEdgeProgress = null;
311
+ lastEdgeTouchX = null;
312
+ lastEdgeTouchY = null;
313
+ activeEdge = null;
314
+ }
315
+ }
316
+ };
317
+
318
+ getActivity()
319
+ .getOnBackInvokedDispatcher()
320
+ .registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT, this.onBackAnimationCallback);
321
+ }
322
+ }
323
+
324
+ private void teardownBackGestureHandlers() {
325
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
326
+ if (this.onBackAnimationCallback == null) {
327
+ return;
328
+ }
329
+
330
+ getActivity().getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(this.onBackAnimationCallback);
331
+ this.onBackAnimationCallback = null;
332
+ }
333
+ }
334
+
335
+ private String getSwipeEdge(int edge) {
336
+ return switch (edge) {
337
+ case EDGE_LEFT -> "left";
338
+ case EDGE_RIGHT -> "right";
339
+ default -> "none";
340
+ };
341
+ }
185
342
  }
@@ -12,6 +12,26 @@ declare module '@capacitor/cli' {
12
12
  * @example true
13
13
  */
14
14
  disableBackButtonHandler?: boolean;
15
+ /**
16
+ * Enable the plugin's edge gesture handler at startup.
17
+ *
18
+ * When enabled, the plugin emits `edgeGesture` events for system edge
19
+ * swipes (iOS left/right screen-edge pans, Android predictive back).
20
+ *
21
+ * On Android, enabling this handler suppresses the default
22
+ * `backButton` handler for the duration that the edge gesture handler
23
+ * is active. The Android predictive-back integration requires API 34
24
+ * (Android 14) or later; on earlier versions the configuration is
25
+ * accepted but no events will be emitted. Android predictive back
26
+ * also requires `android:enableOnBackInvokedCallback="true"` on
27
+ * `<application>` in your `AndroidManifest.xml` (on Android 14;
28
+ * default on Android 15+).
29
+ *
30
+ * @since 9.0.0
31
+ * @default false
32
+ * @example true
33
+ */
34
+ enableEdgeGestureHandler?: boolean;
15
35
  };
16
36
  }
17
37
  }
@@ -130,6 +150,61 @@ export interface BackButtonListenerEvent {
130
150
  */
131
151
  canGoBack: boolean;
132
152
  }
153
+ export interface EdgeGestureListenerEvent {
154
+ /**
155
+ * The current phase of the edge gesture.
156
+ *
157
+ * - `start`: the user has initiated an edge swipe.
158
+ * - `progress`: the user is moving their finger; emitted continuously
159
+ * during the gesture.
160
+ * - `commit`: the user released the gesture and the system accepted it
161
+ * (for example, a back navigation should occur).
162
+ * - `cancel`: the user released the gesture without committing it, or
163
+ * the system cancelled it.
164
+ *
165
+ * @since 9.0.0
166
+ */
167
+ phase: 'start' | 'progress' | 'cancel' | 'commit';
168
+ /**
169
+ * How far the gesture has progressed, normalized between `0` and `1`.
170
+ *
171
+ * On `start` this is the initial progress reported by the system. On
172
+ * `progress` it updates as the user drags. On `commit` and `cancel`
173
+ * it reports the last observed progress value.
174
+ *
175
+ * @since 9.0.0
176
+ */
177
+ progress?: number;
178
+ /**
179
+ * Which screen edge the gesture originated from.
180
+ *
181
+ * On iOS this is `'left'` or `'right'` (left/right screen-edge pans
182
+ * are tracked). On Android this reflects the value reported by the
183
+ * predictive-back system and may also be `'none'` when the platform
184
+ * does not report a specific edge.
185
+ *
186
+ * @since 9.0.0
187
+ */
188
+ swipeEdge?: 'left' | 'right' | 'none';
189
+ /**
190
+ * X coordinate of the touch that initiated or is driving the gesture.
191
+ *
192
+ * On iOS the value is in points relative to the WebView. On Android the
193
+ * value is provided by the platform's `BackEvent.getTouchX()`.
194
+ *
195
+ * @since 9.0.0
196
+ */
197
+ touchX?: number;
198
+ /**
199
+ * Y coordinate of the touch that initiated or is driving the gesture.
200
+ *
201
+ * On iOS the value is in points relative to the WebView. On Android the
202
+ * value is provided by the platform's `BackEvent.getTouchY()`.
203
+ *
204
+ * @since 9.0.0
205
+ */
206
+ touchY?: number;
207
+ }
133
208
  export interface ToggleBackButtonHandlerOptions {
134
209
  /**
135
210
  * Indicates whether to enable or disable default back button handling.
@@ -138,10 +213,19 @@ export interface ToggleBackButtonHandlerOptions {
138
213
  */
139
214
  enabled: boolean;
140
215
  }
216
+ export interface ToggleEdgeGestureHandlerOptions {
217
+ /**
218
+ * Whether to enable or disable the plugin's edge gesture handling.
219
+ *
220
+ * @since 9.0.0
221
+ */
222
+ enabled: boolean;
223
+ }
141
224
  export type StateChangeListener = (state: AppState) => void;
142
225
  export type URLOpenListener = (event: URLOpenListenerEvent) => void;
143
226
  export type RestoredListener = (event: RestoredListenerEvent) => void;
144
227
  export type BackButtonListener = (event: BackButtonListenerEvent) => void;
228
+ export type EdgeGestureListener = (event: EdgeGestureListenerEvent) => void;
145
229
  export interface AppLanguageCode {
146
230
  /**
147
231
  * Two or Three character language code.
@@ -200,6 +284,25 @@ export interface AppPlugin {
200
284
  * @since 7.1.0
201
285
  */
202
286
  toggleBackButtonHandler(options: ToggleBackButtonHandlerOptions): Promise<void>;
287
+ /**
288
+ * Enables or disables the plugin's edge gesture handling at runtime.
289
+ *
290
+ * When enabled, the plugin installs platform edge-gesture recognizers
291
+ * and begins emitting `edgeGesture` events. When disabled, the
292
+ * recognizers are removed and no further events are emitted.
293
+ *
294
+ * On Android, enabling the edge gesture handler temporarily disables
295
+ * the default `backButton` handler; disabling it restores the previous
296
+ * back button handler state. The Android predictive-back integration
297
+ * requires API 34 (Android 14) or later; on earlier versions the call
298
+ * resolves but no events will be emitted. Android predictive back also
299
+ * requires `android:enableOnBackInvokedCallback="true"` on
300
+ * `<application>` in your `AndroidManifest.xml` (on Android 14; default
301
+ * on Android 15+).
302
+ *
303
+ * @since 9.0.0
304
+ */
305
+ toggleEdgeGestureHandler(options: ToggleEdgeGestureHandlerOptions): Promise<void>;
203
306
  /**
204
307
  * Listen for changes in the app or the activity states.
205
308
  *
@@ -273,6 +376,24 @@ export interface AppPlugin {
273
376
  * @since 1.0.0
274
377
  */
275
378
  addListener(eventName: 'backButton', listenerFunc: BackButtonListener): Promise<PluginListenerHandle>;
379
+ /**
380
+ * Listen for system edge-swipe gestures.
381
+ *
382
+ * On iOS this fires for left- and right-edge screen pans tracked by
383
+ * `UIScreenEdgePanGestureRecognizer`. On Android this fires for the
384
+ * predictive back gesture (requires Android 14 / API 34 or later).
385
+ *
386
+ * The edge gesture handler must be active for events to fire; enable
387
+ * it via the `enableEdgeGestureHandler` configuration option or at
388
+ * runtime via `toggleEdgeGestureHandler({ enabled: true })`.
389
+ *
390
+ * Each gesture produces a sequence of events: a single `start`, zero
391
+ * or more `progress`, and then either `commit` (the gesture completed)
392
+ * or `cancel` (the gesture was abandoned).
393
+ *
394
+ * @since 9.0.0
395
+ */
396
+ addListener(eventName: 'edgeGesture', listenerFunc: EdgeGestureListener): Promise<PluginListenerHandle>;
276
397
  /**
277
398
  * Remove all native listeners for this plugin
278
399
  *
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["/// <reference types=\"@capacitor/cli\" />\n\nimport type { PluginListenerHandle } from '@capacitor/core';\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n App?: {\n /**\n * Disable the plugin's default back button handling.\n *\n * Only available for Android.\n *\n * @since 7.1.0\n * @default false\n * @example true\n */\n disableBackButtonHandler?: boolean;\n };\n }\n}\n\nexport interface AppInfo {\n /**\n * The name of the app.\n *\n * @since 1.0.0\n */\n name: string;\n\n /**\n * The identifier of the app.\n * On iOS it's the Bundle Identifier.\n * On Android it's the Application ID\n *\n * @since 1.0.0\n */\n id: string;\n\n /**\n * The build version.\n * On iOS it's the CFBundleVersion.\n * On Android it's the versionCode.\n *\n * @since 1.0.0\n */\n build: string;\n\n /**\n * The app version.\n * On iOS it's the CFBundleShortVersionString.\n * On Android it's package's versionName.\n *\n * @since 1.0.0\n */\n version: string;\n}\n\nexport interface AppState {\n /**\n * Whether the app is active or not.\n *\n * @since 1.0.0\n */\n isActive: boolean;\n}\n\nexport interface URLOpenListenerEvent {\n /**\n * The URL the app was opened with.\n *\n * @since 1.0.0\n */\n url: string;\n\n /**\n * The source application opening the app (iOS only)\n * https://developer.apple.com/documentation/uikit/uiapplicationopenurloptionskey/1623128-sourceapplication\n *\n * @since 1.0.0\n */\n iosSourceApplication?: any;\n /**\n * Whether the app should open the passed document in-place\n * or must copy it first.\n * https://developer.apple.com/documentation/uikit/uiapplicationopenurloptionskey/1623123-openinplace\n *\n * @since 1.0.0\n */\n iosOpenInPlace?: boolean;\n}\n\nexport interface AppLaunchUrl {\n /**\n * The url used to open the app.\n *\n * @since 1.0.0\n */\n url: string;\n}\n\nexport interface RestoredListenerEvent {\n /**\n * The pluginId this result corresponds to. For example, `Camera`.\n *\n * @since 1.0.0\n */\n pluginId: string;\n /**\n * The methodName this result corresponds to. For example, `getPhoto`\n *\n * @since 1.0.0\n */\n methodName: string;\n /**\n * The result data passed from the plugin. This would be the result you'd\n * expect from normally calling the plugin method. For example, `CameraPhoto`\n *\n * @since 1.0.0\n */\n data?: any;\n /**\n * Boolean indicating if the plugin call succeeded.\n *\n * @since 1.0.0\n */\n success: boolean;\n /**\n * If the plugin call didn't succeed, it will contain the error message.\n *\n * @since 1.0.0\n */\n error?: {\n message: string;\n };\n}\n\nexport interface BackButtonListenerEvent {\n /**\n * Indicates whether the browser can go back in history.\n * False when the history stack is on the first entry.\n *\n * @since 1.0.0\n */\n canGoBack: boolean;\n}\n\nexport interface ToggleBackButtonHandlerOptions {\n /**\n * Indicates whether to enable or disable default back button handling.\n *\n * @since 7.1.0\n */\n enabled: boolean;\n}\n\nexport type StateChangeListener = (state: AppState) => void;\nexport type URLOpenListener = (event: URLOpenListenerEvent) => void;\nexport type RestoredListener = (event: RestoredListenerEvent) => void;\nexport type BackButtonListener = (event: BackButtonListenerEvent) => void;\n\nexport interface AppLanguageCode {\n /**\n * Two or Three character language code.\n *\n * @since 8.1.0\n */\n value: string;\n}\n\nexport interface AppPlugin {\n /**\n * Force exit the app. This should only be used in conjunction with the `backButton` handler for Android to\n * exit the app when navigation is complete.\n *\n * Ionic handles this itself so you shouldn't need to call this if using Ionic.\n *\n * @since 1.0.0\n */\n exitApp(): Promise<void>;\n\n /**\n * Return information about the app.\n *\n * @since 1.0.0\n */\n getInfo(): Promise<AppInfo>;\n\n /**\n * Gets the current app state.\n *\n * @since 1.0.0\n */\n getState(): Promise<AppState>;\n\n /**\n * Get the URL the app was launched with, if any.\n *\n * @since 1.0.0\n */\n getLaunchUrl(): Promise<AppLaunchUrl | undefined>;\n\n /**\n * Minimizes the application.\n *\n * Only available for Android.\n *\n * @since 1.1.0\n */\n minimizeApp(): Promise<void>;\n\n /**\n * Get the app specific language locale code.\n *\n * @since 8.1.0\n */\n getAppLanguage(): Promise<AppLanguageCode>;\n\n /**\n * Enables or disables the plugin's back button handling during runtime.\n *\n * Only available for Android.\n *\n * @since 7.1.0\n */\n toggleBackButtonHandler(options: ToggleBackButtonHandlerOptions): Promise<void>;\n\n /**\n * Listen for changes in the app or the activity states.\n *\n * On iOS it's fired when the native [UIApplication.willResignActiveNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622973-willresignactivenotification) and\n * [UIApplication.didBecomeActiveNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622953-didbecomeactivenotification) events get fired.\n * On Android it's fired when the Capacitor's Activity [onResume](https://developer.android.com/reference/android/app/Activity#onResume()) and [onStop](https://developer.android.com/reference/android/app/Activity#onStop()) methods gets called.\n * On Web it's fired when the document's visibilitychange gets fired.\n *\n * @since 1.0.0\n */\n addListener(eventName: 'appStateChange', listenerFunc: StateChangeListener): Promise<PluginListenerHandle>;\n\n /**\n * Listen for when the app or the activity are paused.\n *\n * On iOS it's fired when the native [UIApplication.didEnterBackgroundNotification](https://developer.apple.com/documentation/uikit/uiapplication/1623071-didenterbackgroundnotification) event gets fired.\n * On Android it's fired when the Capacitor's Activity [onPause](https://developer.android.com/reference/android/app/Activity#onPause()) method gets called.\n * On Web it's fired when the document's visibilitychange gets fired and document.hidden is true.\n *\n * @since 4.1.0\n */\n addListener(eventName: 'pause', listenerFunc: () => void): Promise<PluginListenerHandle>;\n\n /**\n * Listen for when the app or activity are resumed.\n *\n * On iOS it's fired when the native [UIApplication.willEnterForegroundNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622944-willenterforegroundnotification) event gets fired.\n * On Android it's fired when the Capacitor's Activity [onResume](https://developer.android.com/reference/android/app/Activity#onResume()) method gets called,\n * but only after resume has fired first.\n * On Web it's fired when the document's visibilitychange gets fired and document.hidden is false.\n *\n * @since 4.1.0\n */\n addListener(eventName: 'resume', listenerFunc: () => void): Promise<PluginListenerHandle>;\n\n /**\n * Listen for url open events for the app. This handles both custom URL scheme links as well\n * as URLs your app handles (Universal Links on iOS and App Links on Android)\n *\n * @since 1.0.0\n */\n addListener(eventName: 'appUrlOpen', listenerFunc: URLOpenListener): Promise<PluginListenerHandle>;\n\n /**\n * If the app was launched with previously persisted plugin call data, such as on Android\n * when an activity returns to an app that was closed, this call will return any data\n * the app was launched with, converted into the form of a result from a plugin call.\n *\n * On Android, due to memory constraints on low-end devices, it's possible\n * that, if your app launches a new activity, your app will be terminated by\n * the operating system in order to reduce memory consumption.\n *\n * For example, that means the Camera API, which launches a new Activity to\n * take a photo, may not be able to return data back to your app.\n *\n * To avoid this, Capacitor stores all restored activity results on launch.\n * You should add a listener for `appRestoredResult` in order to handle any\n * plugin call results that were delivered when your app was not running.\n *\n * Once you have that result (if any), you can update the UI to restore a\n * logical experience for the user, such as navigating or selecting the\n * proper tab.\n *\n * We recommend every Android app using plugins that rely on external\n * Activities (for example, Camera) to have this event and process handled.\n *\n * @since 1.0.0\n */\n addListener(eventName: 'appRestoredResult', listenerFunc: RestoredListener): Promise<PluginListenerHandle>;\n\n /**\n * Listen for the hardware back button event (Android only). Listening for this event will disable the\n * default back button behaviour, so you might want to call `window.history.back()` manually.\n * If you want to close the app, call `App.exitApp()`.\n *\n * @since 1.0.0\n */\n addListener(eventName: 'backButton', listenerFunc: BackButtonListener): Promise<PluginListenerHandle>;\n\n /**\n * Remove all native listeners for this plugin\n *\n * @since 1.0.0\n */\n removeAllListeners(): Promise<void>;\n}\n"]}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["/// <reference types=\"@capacitor/cli\" />\n\nimport type { PluginListenerHandle } from '@capacitor/core';\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n App?: {\n /**\n * Disable the plugin's default back button handling.\n *\n * Only available for Android.\n *\n * @since 7.1.0\n * @default false\n * @example true\n */\n disableBackButtonHandler?: boolean;\n\n /**\n * Enable the plugin's edge gesture handler at startup.\n *\n * When enabled, the plugin emits `edgeGesture` events for system edge\n * swipes (iOS left/right screen-edge pans, Android predictive back).\n *\n * On Android, enabling this handler suppresses the default\n * `backButton` handler for the duration that the edge gesture handler\n * is active. The Android predictive-back integration requires API 34\n * (Android 14) or later; on earlier versions the configuration is\n * accepted but no events will be emitted. Android predictive back\n * also requires `android:enableOnBackInvokedCallback=\"true\"` on\n * `<application>` in your `AndroidManifest.xml` (on Android 14;\n * default on Android 15+).\n *\n * @since 9.0.0\n * @default false\n * @example true\n */\n enableEdgeGestureHandler?: boolean;\n };\n }\n}\n\nexport interface AppInfo {\n /**\n * The name of the app.\n *\n * @since 1.0.0\n */\n name: string;\n\n /**\n * The identifier of the app.\n * On iOS it's the Bundle Identifier.\n * On Android it's the Application ID\n *\n * @since 1.0.0\n */\n id: string;\n\n /**\n * The build version.\n * On iOS it's the CFBundleVersion.\n * On Android it's the versionCode.\n *\n * @since 1.0.0\n */\n build: string;\n\n /**\n * The app version.\n * On iOS it's the CFBundleShortVersionString.\n * On Android it's package's versionName.\n *\n * @since 1.0.0\n */\n version: string;\n}\n\nexport interface AppState {\n /**\n * Whether the app is active or not.\n *\n * @since 1.0.0\n */\n isActive: boolean;\n}\n\nexport interface URLOpenListenerEvent {\n /**\n * The URL the app was opened with.\n *\n * @since 1.0.0\n */\n url: string;\n\n /**\n * The source application opening the app (iOS only)\n * https://developer.apple.com/documentation/uikit/uiapplicationopenurloptionskey/1623128-sourceapplication\n *\n * @since 1.0.0\n */\n iosSourceApplication?: any;\n /**\n * Whether the app should open the passed document in-place\n * or must copy it first.\n * https://developer.apple.com/documentation/uikit/uiapplicationopenurloptionskey/1623123-openinplace\n *\n * @since 1.0.0\n */\n iosOpenInPlace?: boolean;\n}\n\nexport interface AppLaunchUrl {\n /**\n * The url used to open the app.\n *\n * @since 1.0.0\n */\n url: string;\n}\n\nexport interface RestoredListenerEvent {\n /**\n * The pluginId this result corresponds to. For example, `Camera`.\n *\n * @since 1.0.0\n */\n pluginId: string;\n /**\n * The methodName this result corresponds to. For example, `getPhoto`\n *\n * @since 1.0.0\n */\n methodName: string;\n /**\n * The result data passed from the plugin. This would be the result you'd\n * expect from normally calling the plugin method. For example, `CameraPhoto`\n *\n * @since 1.0.0\n */\n data?: any;\n /**\n * Boolean indicating if the plugin call succeeded.\n *\n * @since 1.0.0\n */\n success: boolean;\n /**\n * If the plugin call didn't succeed, it will contain the error message.\n *\n * @since 1.0.0\n */\n error?: {\n message: string;\n };\n}\n\nexport interface BackButtonListenerEvent {\n /**\n * Indicates whether the browser can go back in history.\n * False when the history stack is on the first entry.\n *\n * @since 1.0.0\n */\n canGoBack: boolean;\n}\n\nexport interface EdgeGestureListenerEvent {\n /**\n * The current phase of the edge gesture.\n *\n * - `start`: the user has initiated an edge swipe.\n * - `progress`: the user is moving their finger; emitted continuously\n * during the gesture.\n * - `commit`: the user released the gesture and the system accepted it\n * (for example, a back navigation should occur).\n * - `cancel`: the user released the gesture without committing it, or\n * the system cancelled it.\n *\n * @since 9.0.0\n */\n phase: 'start' | 'progress' | 'cancel' | 'commit';\n\n /**\n * How far the gesture has progressed, normalized between `0` and `1`.\n *\n * On `start` this is the initial progress reported by the system. On\n * `progress` it updates as the user drags. On `commit` and `cancel`\n * it reports the last observed progress value.\n *\n * @since 9.0.0\n */\n progress?: number;\n\n /**\n * Which screen edge the gesture originated from.\n *\n * On iOS this is `'left'` or `'right'` (left/right screen-edge pans\n * are tracked). On Android this reflects the value reported by the\n * predictive-back system and may also be `'none'` when the platform\n * does not report a specific edge.\n *\n * @since 9.0.0\n */\n swipeEdge?: 'left' | 'right' | 'none';\n\n /**\n * X coordinate of the touch that initiated or is driving the gesture.\n *\n * On iOS the value is in points relative to the WebView. On Android the\n * value is provided by the platform's `BackEvent.getTouchX()`.\n *\n * @since 9.0.0\n */\n touchX?: number;\n\n /**\n * Y coordinate of the touch that initiated or is driving the gesture.\n *\n * On iOS the value is in points relative to the WebView. On Android the\n * value is provided by the platform's `BackEvent.getTouchY()`.\n *\n * @since 9.0.0\n */\n touchY?: number;\n}\n\nexport interface ToggleBackButtonHandlerOptions {\n /**\n * Indicates whether to enable or disable default back button handling.\n *\n * @since 7.1.0\n */\n enabled: boolean;\n}\n\nexport interface ToggleEdgeGestureHandlerOptions {\n /**\n * Whether to enable or disable the plugin's edge gesture handling.\n *\n * @since 9.0.0\n */\n enabled: boolean;\n}\n\nexport type StateChangeListener = (state: AppState) => void;\nexport type URLOpenListener = (event: URLOpenListenerEvent) => void;\nexport type RestoredListener = (event: RestoredListenerEvent) => void;\nexport type BackButtonListener = (event: BackButtonListenerEvent) => void;\nexport type EdgeGestureListener = (event: EdgeGestureListenerEvent) => void;\n\nexport interface AppLanguageCode {\n /**\n * Two or Three character language code.\n *\n * @since 8.1.0\n */\n value: string;\n}\n\nexport interface AppPlugin {\n /**\n * Force exit the app. This should only be used in conjunction with the `backButton` handler for Android to\n * exit the app when navigation is complete.\n *\n * Ionic handles this itself so you shouldn't need to call this if using Ionic.\n *\n * @since 1.0.0\n */\n exitApp(): Promise<void>;\n\n /**\n * Return information about the app.\n *\n * @since 1.0.0\n */\n getInfo(): Promise<AppInfo>;\n\n /**\n * Gets the current app state.\n *\n * @since 1.0.0\n */\n getState(): Promise<AppState>;\n\n /**\n * Get the URL the app was launched with, if any.\n *\n * @since 1.0.0\n */\n getLaunchUrl(): Promise<AppLaunchUrl | undefined>;\n\n /**\n * Minimizes the application.\n *\n * Only available for Android.\n *\n * @since 1.1.0\n */\n minimizeApp(): Promise<void>;\n\n /**\n * Get the app specific language locale code.\n *\n * @since 8.1.0\n */\n getAppLanguage(): Promise<AppLanguageCode>;\n\n /**\n * Enables or disables the plugin's back button handling during runtime.\n *\n * Only available for Android.\n *\n * @since 7.1.0\n */\n toggleBackButtonHandler(options: ToggleBackButtonHandlerOptions): Promise<void>;\n\n /**\n * Enables or disables the plugin's edge gesture handling at runtime.\n *\n * When enabled, the plugin installs platform edge-gesture recognizers\n * and begins emitting `edgeGesture` events. When disabled, the\n * recognizers are removed and no further events are emitted.\n *\n * On Android, enabling the edge gesture handler temporarily disables\n * the default `backButton` handler; disabling it restores the previous\n * back button handler state. The Android predictive-back integration\n * requires API 34 (Android 14) or later; on earlier versions the call\n * resolves but no events will be emitted. Android predictive back also\n * requires `android:enableOnBackInvokedCallback=\"true\"` on\n * `<application>` in your `AndroidManifest.xml` (on Android 14; default\n * on Android 15+).\n *\n * @since 9.0.0\n */\n toggleEdgeGestureHandler(options: ToggleEdgeGestureHandlerOptions): Promise<void>;\n\n /**\n * Listen for changes in the app or the activity states.\n *\n * On iOS it's fired when the native [UIApplication.willResignActiveNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622973-willresignactivenotification) and\n * [UIApplication.didBecomeActiveNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622953-didbecomeactivenotification) events get fired.\n * On Android it's fired when the Capacitor's Activity [onResume](https://developer.android.com/reference/android/app/Activity#onResume()) and [onStop](https://developer.android.com/reference/android/app/Activity#onStop()) methods gets called.\n * On Web it's fired when the document's visibilitychange gets fired.\n *\n * @since 1.0.0\n */\n addListener(eventName: 'appStateChange', listenerFunc: StateChangeListener): Promise<PluginListenerHandle>;\n\n /**\n * Listen for when the app or the activity are paused.\n *\n * On iOS it's fired when the native [UIApplication.didEnterBackgroundNotification](https://developer.apple.com/documentation/uikit/uiapplication/1623071-didenterbackgroundnotification) event gets fired.\n * On Android it's fired when the Capacitor's Activity [onPause](https://developer.android.com/reference/android/app/Activity#onPause()) method gets called.\n * On Web it's fired when the document's visibilitychange gets fired and document.hidden is true.\n *\n * @since 4.1.0\n */\n addListener(eventName: 'pause', listenerFunc: () => void): Promise<PluginListenerHandle>;\n\n /**\n * Listen for when the app or activity are resumed.\n *\n * On iOS it's fired when the native [UIApplication.willEnterForegroundNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622944-willenterforegroundnotification) event gets fired.\n * On Android it's fired when the Capacitor's Activity [onResume](https://developer.android.com/reference/android/app/Activity#onResume()) method gets called,\n * but only after resume has fired first.\n * On Web it's fired when the document's visibilitychange gets fired and document.hidden is false.\n *\n * @since 4.1.0\n */\n addListener(eventName: 'resume', listenerFunc: () => void): Promise<PluginListenerHandle>;\n\n /**\n * Listen for url open events for the app. This handles both custom URL scheme links as well\n * as URLs your app handles (Universal Links on iOS and App Links on Android)\n *\n * @since 1.0.0\n */\n addListener(eventName: 'appUrlOpen', listenerFunc: URLOpenListener): Promise<PluginListenerHandle>;\n\n /**\n * If the app was launched with previously persisted plugin call data, such as on Android\n * when an activity returns to an app that was closed, this call will return any data\n * the app was launched with, converted into the form of a result from a plugin call.\n *\n * On Android, due to memory constraints on low-end devices, it's possible\n * that, if your app launches a new activity, your app will be terminated by\n * the operating system in order to reduce memory consumption.\n *\n * For example, that means the Camera API, which launches a new Activity to\n * take a photo, may not be able to return data back to your app.\n *\n * To avoid this, Capacitor stores all restored activity results on launch.\n * You should add a listener for `appRestoredResult` in order to handle any\n * plugin call results that were delivered when your app was not running.\n *\n * Once you have that result (if any), you can update the UI to restore a\n * logical experience for the user, such as navigating or selecting the\n * proper tab.\n *\n * We recommend every Android app using plugins that rely on external\n * Activities (for example, Camera) to have this event and process handled.\n *\n * @since 1.0.0\n */\n addListener(eventName: 'appRestoredResult', listenerFunc: RestoredListener): Promise<PluginListenerHandle>;\n\n /**\n * Listen for the hardware back button event (Android only). Listening for this event will disable the\n * default back button behaviour, so you might want to call `window.history.back()` manually.\n * If you want to close the app, call `App.exitApp()`.\n *\n * @since 1.0.0\n */\n addListener(eventName: 'backButton', listenerFunc: BackButtonListener): Promise<PluginListenerHandle>;\n\n /**\n * Listen for system edge-swipe gestures.\n *\n * On iOS this fires for left- and right-edge screen pans tracked by\n * `UIScreenEdgePanGestureRecognizer`. On Android this fires for the\n * predictive back gesture (requires Android 14 / API 34 or later).\n *\n * The edge gesture handler must be active for events to fire; enable\n * it via the `enableEdgeGestureHandler` configuration option or at\n * runtime via `toggleEdgeGestureHandler({ enabled: true })`.\n *\n * Each gesture produces a sequence of events: a single `start`, zero\n * or more `progress`, and then either `commit` (the gesture completed)\n * or `cancel` (the gesture was abandoned).\n *\n * @since 9.0.0\n */\n addListener(eventName: 'edgeGesture', listenerFunc: EdgeGestureListener): Promise<PluginListenerHandle>;\n\n /**\n * Remove all native listeners for this plugin\n *\n * @since 1.0.0\n */\n removeAllListeners(): Promise<void>;\n}\n"]}
package/dist/esm/web.d.ts CHANGED
@@ -8,6 +8,7 @@ export declare class AppWeb extends WebPlugin implements AppPlugin {
8
8
  getState(): Promise<AppState>;
9
9
  minimizeApp(): Promise<void>;
10
10
  toggleBackButtonHandler(): Promise<void>;
11
+ toggleEdgeGestureHandler(): Promise<void>;
11
12
  private handleVisibilityChange;
12
13
  getAppLanguage(): Promise<AppLanguageCode>;
13
14
  }
package/dist/esm/web.js CHANGED
@@ -34,6 +34,9 @@ export class AppWeb extends WebPlugin {
34
34
  async toggleBackButtonHandler() {
35
35
  throw this.unimplemented('Not implemented on web.');
36
36
  }
37
+ async toggleEdgeGestureHandler() {
38
+ throw this.unimplemented('Not implemented on web.');
39
+ }
37
40
  async getAppLanguage() {
38
41
  return {
39
42
  value: navigator.language.split('-')[0].toLowerCase(),
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,MAAO,SAAQ,SAAS;IACnC;QACE,KAAK,EAAE,CAAC;QA4BF,2BAAsB,GAAG,GAAG,EAAE;YACpC,MAAM,IAAI,GAAG;gBACX,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI;aACnC,CAAC;YAEF,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;YAC7C,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACpB,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;QAtCA,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;IACpF,CAAC;IAED,OAAO;QACL,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,WAAW;QACf,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,uBAAuB;QAC3B,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;IAeD,KAAK,CAAC,cAAc;QAClB,OAAO;YACL,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;SACtD,CAAC;IACJ,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type { AppInfo, AppPlugin, AppLaunchUrl, AppState, AppLanguageCode } from './definitions';\n\nexport class AppWeb extends WebPlugin implements AppPlugin {\n constructor() {\n super();\n document.addEventListener('visibilitychange', this.handleVisibilityChange, false);\n }\n\n exitApp(): Promise<void> {\n throw this.unimplemented('Not implemented on web.');\n }\n\n async getInfo(): Promise<AppInfo> {\n throw this.unimplemented('Not implemented on web.');\n }\n\n async getLaunchUrl(): Promise<AppLaunchUrl> {\n return { url: '' };\n }\n\n async getState(): Promise<AppState> {\n return { isActive: document.hidden !== true };\n }\n\n async minimizeApp(): Promise<void> {\n throw this.unimplemented('Not implemented on web.');\n }\n\n async toggleBackButtonHandler(): Promise<void> {\n throw this.unimplemented('Not implemented on web.');\n }\n\n private handleVisibilityChange = () => {\n const data = {\n isActive: document.hidden !== true,\n };\n\n this.notifyListeners('appStateChange', data);\n if (document.hidden) {\n this.notifyListeners('pause', null);\n } else {\n this.notifyListeners('resume', null);\n }\n };\n\n async getAppLanguage(): Promise<AppLanguageCode> {\n return {\n value: navigator.language.split('-')[0].toLowerCase(),\n };\n }\n}\n"]}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,MAAO,SAAQ,SAAS;IACnC;QACE,KAAK,EAAE,CAAC;QAgCF,2BAAsB,GAAG,GAAG,EAAE;YACpC,MAAM,IAAI,GAAG;gBACX,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI;aACnC,CAAC;YAEF,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;YAC7C,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACpB,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;QA1CA,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;IACpF,CAAC;IAED,OAAO;QACL,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,WAAW;QACf,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,uBAAuB;QAC3B,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,wBAAwB;QAC5B,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;IAeD,KAAK,CAAC,cAAc;QAClB,OAAO;YACL,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;SACtD,CAAC;IACJ,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type { AppInfo, AppPlugin, AppLaunchUrl, AppState, AppLanguageCode } from './definitions';\n\nexport class AppWeb extends WebPlugin implements AppPlugin {\n constructor() {\n super();\n document.addEventListener('visibilitychange', this.handleVisibilityChange, false);\n }\n\n exitApp(): Promise<void> {\n throw this.unimplemented('Not implemented on web.');\n }\n\n async getInfo(): Promise<AppInfo> {\n throw this.unimplemented('Not implemented on web.');\n }\n\n async getLaunchUrl(): Promise<AppLaunchUrl> {\n return { url: '' };\n }\n\n async getState(): Promise<AppState> {\n return { isActive: document.hidden !== true };\n }\n\n async minimizeApp(): Promise<void> {\n throw this.unimplemented('Not implemented on web.');\n }\n\n async toggleBackButtonHandler(): Promise<void> {\n throw this.unimplemented('Not implemented on web.');\n }\n\n async toggleEdgeGestureHandler(): Promise<void> {\n throw this.unimplemented('Not implemented on web.');\n }\n\n private handleVisibilityChange = () => {\n const data = {\n isActive: document.hidden !== true,\n };\n\n this.notifyListeners('appStateChange', data);\n if (document.hidden) {\n this.notifyListeners('pause', null);\n } else {\n this.notifyListeners('resume', null);\n }\n };\n\n async getAppLanguage(): Promise<AppLanguageCode> {\n return {\n value: navigator.language.split('-')[0].toLowerCase(),\n };\n }\n}\n"]}
@@ -41,6 +41,9 @@ class AppWeb extends core.WebPlugin {
41
41
  async toggleBackButtonHandler() {
42
42
  throw this.unimplemented('Not implemented on web.');
43
43
  }
44
+ async toggleEdgeGestureHandler() {
45
+ throw this.unimplemented('Not implemented on web.');
46
+ }
44
47
  async getAppLanguage() {
45
48
  return {
46
49
  value: navigator.language.split('-')[0].toLowerCase(),
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst App = registerPlugin('App', {\n web: () => import('./web').then((m) => new m.AppWeb()),\n});\nexport * from './definitions';\nexport { App };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class AppWeb extends WebPlugin {\n constructor() {\n super();\n this.handleVisibilityChange = () => {\n const data = {\n isActive: document.hidden !== true,\n };\n this.notifyListeners('appStateChange', data);\n if (document.hidden) {\n this.notifyListeners('pause', null);\n }\n else {\n this.notifyListeners('resume', null);\n }\n };\n document.addEventListener('visibilitychange', this.handleVisibilityChange, false);\n }\n exitApp() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getInfo() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getLaunchUrl() {\n return { url: '' };\n }\n async getState() {\n return { isActive: document.hidden !== true };\n }\n async minimizeApp() {\n throw this.unimplemented('Not implemented on web.');\n }\n async toggleBackButtonHandler() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getAppLanguage() {\n return {\n value: navigator.language.split('-')[0].toLowerCase(),\n };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,GAAG,GAAGA,mBAAc,CAAC,KAAK,EAAE;AAClC,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;AAC1D,CAAC;;ACFM,MAAM,MAAM,SAASC,cAAS,CAAC;AACtC,IAAI,WAAW,GAAG;AAClB,QAAQ,KAAK,EAAE;AACf,QAAQ,IAAI,CAAC,sBAAsB,GAAG,MAAM;AAC5C,YAAY,MAAM,IAAI,GAAG;AACzB,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI;AAClD,aAAa;AACb,YAAY,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,IAAI,CAAC;AACxD,YAAY,IAAI,QAAQ,CAAC,MAAM,EAAE;AACjC,gBAAgB,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC;AACnD,YAAY;AACZ,iBAAiB;AACjB,gBAAgB,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC;AACpD,YAAY;AACZ,QAAQ,CAAC;AACT,QAAQ,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC;AACzF,IAAI;AACJ,IAAI,OAAO,GAAG;AACd,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AAC3D,IAAI;AACJ,IAAI,MAAM,OAAO,GAAG;AACpB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AAC3D,IAAI;AACJ,IAAI,MAAM,YAAY,GAAG;AACzB,QAAQ,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE;AAC1B,IAAI;AACJ,IAAI,MAAM,QAAQ,GAAG;AACrB,QAAQ,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE;AACrD,IAAI;AACJ,IAAI,MAAM,WAAW,GAAG;AACxB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AAC3D,IAAI;AACJ,IAAI,MAAM,uBAAuB,GAAG;AACpC,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AAC3D,IAAI;AACJ,IAAI,MAAM,cAAc,GAAG;AAC3B,QAAQ,OAAO;AACf,YAAY,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;AACjE,SAAS;AACT,IAAI;AACJ;;;;;;;;;"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst App = registerPlugin('App', {\n web: () => import('./web').then((m) => new m.AppWeb()),\n});\nexport * from './definitions';\nexport { App };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class AppWeb extends WebPlugin {\n constructor() {\n super();\n this.handleVisibilityChange = () => {\n const data = {\n isActive: document.hidden !== true,\n };\n this.notifyListeners('appStateChange', data);\n if (document.hidden) {\n this.notifyListeners('pause', null);\n }\n else {\n this.notifyListeners('resume', null);\n }\n };\n document.addEventListener('visibilitychange', this.handleVisibilityChange, false);\n }\n exitApp() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getInfo() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getLaunchUrl() {\n return { url: '' };\n }\n async getState() {\n return { isActive: document.hidden !== true };\n }\n async minimizeApp() {\n throw this.unimplemented('Not implemented on web.');\n }\n async toggleBackButtonHandler() {\n throw this.unimplemented('Not implemented on web.');\n }\n async toggleEdgeGestureHandler() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getAppLanguage() {\n return {\n value: navigator.language.split('-')[0].toLowerCase(),\n };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,GAAG,GAAGA,mBAAc,CAAC,KAAK,EAAE;AAClC,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;AAC1D,CAAC;;ACFM,MAAM,MAAM,SAASC,cAAS,CAAC;AACtC,IAAI,WAAW,GAAG;AAClB,QAAQ,KAAK,EAAE;AACf,QAAQ,IAAI,CAAC,sBAAsB,GAAG,MAAM;AAC5C,YAAY,MAAM,IAAI,GAAG;AACzB,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI;AAClD,aAAa;AACb,YAAY,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,IAAI,CAAC;AACxD,YAAY,IAAI,QAAQ,CAAC,MAAM,EAAE;AACjC,gBAAgB,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC;AACnD,YAAY;AACZ,iBAAiB;AACjB,gBAAgB,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC;AACpD,YAAY;AACZ,QAAQ,CAAC;AACT,QAAQ,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC;AACzF,IAAI;AACJ,IAAI,OAAO,GAAG;AACd,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AAC3D,IAAI;AACJ,IAAI,MAAM,OAAO,GAAG;AACpB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AAC3D,IAAI;AACJ,IAAI,MAAM,YAAY,GAAG;AACzB,QAAQ,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE;AAC1B,IAAI;AACJ,IAAI,MAAM,QAAQ,GAAG;AACrB,QAAQ,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE;AACrD,IAAI;AACJ,IAAI,MAAM,WAAW,GAAG;AACxB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AAC3D,IAAI;AACJ,IAAI,MAAM,uBAAuB,GAAG;AACpC,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AAC3D,IAAI;AACJ,IAAI,MAAM,wBAAwB,GAAG;AACrC,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AAC3D,IAAI;AACJ,IAAI,MAAM,cAAc,GAAG;AAC3B,QAAQ,OAAO;AACf,YAAY,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;AACjE,SAAS;AACT,IAAI;AACJ;;;;;;;;;"}
package/dist/plugin.js CHANGED
@@ -40,6 +40,9 @@ var capacitorApp = (function (exports, core) {
40
40
  async toggleBackButtonHandler() {
41
41
  throw this.unimplemented('Not implemented on web.');
42
42
  }
43
+ async toggleEdgeGestureHandler() {
44
+ throw this.unimplemented('Not implemented on web.');
45
+ }
43
46
  async getAppLanguage() {
44
47
  return {
45
48
  value: navigator.language.split('-')[0].toLowerCase(),
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst App = registerPlugin('App', {\n web: () => import('./web').then((m) => new m.AppWeb()),\n});\nexport * from './definitions';\nexport { App };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class AppWeb extends WebPlugin {\n constructor() {\n super();\n this.handleVisibilityChange = () => {\n const data = {\n isActive: document.hidden !== true,\n };\n this.notifyListeners('appStateChange', data);\n if (document.hidden) {\n this.notifyListeners('pause', null);\n }\n else {\n this.notifyListeners('resume', null);\n }\n };\n document.addEventListener('visibilitychange', this.handleVisibilityChange, false);\n }\n exitApp() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getInfo() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getLaunchUrl() {\n return { url: '' };\n }\n async getState() {\n return { isActive: document.hidden !== true };\n }\n async minimizeApp() {\n throw this.unimplemented('Not implemented on web.');\n }\n async toggleBackButtonHandler() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getAppLanguage() {\n return {\n value: navigator.language.split('-')[0].toLowerCase(),\n };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,GAAG,GAAGA,mBAAc,CAAC,KAAK,EAAE;IAClC,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;IAC1D,CAAC;;ICFM,MAAM,MAAM,SAASC,cAAS,CAAC;IACtC,IAAI,WAAW,GAAG;IAClB,QAAQ,KAAK,EAAE;IACf,QAAQ,IAAI,CAAC,sBAAsB,GAAG,MAAM;IAC5C,YAAY,MAAM,IAAI,GAAG;IACzB,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI;IAClD,aAAa;IACb,YAAY,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,IAAI,CAAC;IACxD,YAAY,IAAI,QAAQ,CAAC,MAAM,EAAE;IACjC,gBAAgB,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC;IACnD,YAAY;IACZ,iBAAiB;IACjB,gBAAgB,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC;IACpD,YAAY;IACZ,QAAQ,CAAC;IACT,QAAQ,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC;IACzF,IAAI;IACJ,IAAI,OAAO,GAAG;IACd,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D,IAAI;IACJ,IAAI,MAAM,OAAO,GAAG;IACpB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D,IAAI;IACJ,IAAI,MAAM,YAAY,GAAG;IACzB,QAAQ,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE;IAC1B,IAAI;IACJ,IAAI,MAAM,QAAQ,GAAG;IACrB,QAAQ,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE;IACrD,IAAI;IACJ,IAAI,MAAM,WAAW,GAAG;IACxB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D,IAAI;IACJ,IAAI,MAAM,uBAAuB,GAAG;IACpC,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D,IAAI;IACJ,IAAI,MAAM,cAAc,GAAG;IAC3B,QAAQ,OAAO;IACf,YAAY,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;IACjE,SAAS;IACT,IAAI;IACJ;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst App = registerPlugin('App', {\n web: () => import('./web').then((m) => new m.AppWeb()),\n});\nexport * from './definitions';\nexport { App };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class AppWeb extends WebPlugin {\n constructor() {\n super();\n this.handleVisibilityChange = () => {\n const data = {\n isActive: document.hidden !== true,\n };\n this.notifyListeners('appStateChange', data);\n if (document.hidden) {\n this.notifyListeners('pause', null);\n }\n else {\n this.notifyListeners('resume', null);\n }\n };\n document.addEventListener('visibilitychange', this.handleVisibilityChange, false);\n }\n exitApp() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getInfo() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getLaunchUrl() {\n return { url: '' };\n }\n async getState() {\n return { isActive: document.hidden !== true };\n }\n async minimizeApp() {\n throw this.unimplemented('Not implemented on web.');\n }\n async toggleBackButtonHandler() {\n throw this.unimplemented('Not implemented on web.');\n }\n async toggleEdgeGestureHandler() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getAppLanguage() {\n return {\n value: navigator.language.split('-')[0].toLowerCase(),\n };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,GAAG,GAAGA,mBAAc,CAAC,KAAK,EAAE;IAClC,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;IAC1D,CAAC;;ICFM,MAAM,MAAM,SAASC,cAAS,CAAC;IACtC,IAAI,WAAW,GAAG;IAClB,QAAQ,KAAK,EAAE;IACf,QAAQ,IAAI,CAAC,sBAAsB,GAAG,MAAM;IAC5C,YAAY,MAAM,IAAI,GAAG;IACzB,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI;IAClD,aAAa;IACb,YAAY,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,IAAI,CAAC;IACxD,YAAY,IAAI,QAAQ,CAAC,MAAM,EAAE;IACjC,gBAAgB,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC;IACnD,YAAY;IACZ,iBAAiB;IACjB,gBAAgB,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC;IACpD,YAAY;IACZ,QAAQ,CAAC;IACT,QAAQ,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC;IACzF,IAAI;IACJ,IAAI,OAAO,GAAG;IACd,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D,IAAI;IACJ,IAAI,MAAM,OAAO,GAAG;IACpB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D,IAAI;IACJ,IAAI,MAAM,YAAY,GAAG;IACzB,QAAQ,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE;IAC1B,IAAI;IACJ,IAAI,MAAM,QAAQ,GAAG;IACrB,QAAQ,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE;IACrD,IAAI;IACJ,IAAI,MAAM,WAAW,GAAG;IACxB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D,IAAI;IACJ,IAAI,MAAM,uBAAuB,GAAG;IACpC,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D,IAAI;IACJ,IAAI,MAAM,wBAAwB,GAAG;IACrC,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D,IAAI;IACJ,IAAI,MAAM,cAAc,GAAG;IAC3B,QAAQ,OAAO;IACf,YAAY,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;IACjE,SAAS;IACT,IAAI;IACJ;;;;;;;;;;;;;;;"}
@@ -12,11 +12,20 @@ public class AppPlugin: CAPPlugin, CAPBridgedPlugin {
12
12
  CAPPluginMethod(name: "getLaunchUrl", returnType: CAPPluginReturnPromise),
13
13
  CAPPluginMethod(name: "getState", returnType: CAPPluginReturnPromise),
14
14
  CAPPluginMethod(name: "minimizeApp", returnType: CAPPluginReturnPromise),
15
- CAPPluginMethod(name: "toggleBackButtonHandler", returnType: CAPPluginReturnPromise)
15
+ CAPPluginMethod(name: "toggleBackButtonHandler", returnType: CAPPluginReturnPromise),
16
+ CAPPluginMethod(name: "toggleEdgeGestureHandler", returnType: CAPPluginReturnPromise)
16
17
  ]
17
18
  private var observers: [NSObjectProtocol] = []
19
+ private var leftEdgePanRecognizer: UIScreenEdgePanGestureRecognizer?
20
+ private var rightEdgePanRecognizer: UIScreenEdgePanGestureRecognizer?
18
21
 
19
22
  override public func load() {
23
+ if getConfig().getBoolean("enableEdgeGestureHandler", false) {
24
+ DispatchQueue.main.async { [weak self] in
25
+ self?.loadGestureRecognizers()
26
+ }
27
+ }
28
+
20
29
  NotificationCenter.default.addObserver(self, selector: #selector(self.handleUrlOpened(notification:)), name: Notification.Name.capacitorOpenURL, object: nil)
21
30
  NotificationCenter.default.addObserver(self, selector: #selector(self.handleUniversalLink(notification:)), name: Notification.Name.capacitorOpenUniversalLink, object: nil)
22
31
  observers.append(NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: OperationQueue.main) { [weak self] (_) in
@@ -125,4 +134,104 @@ public class AppPlugin: CAPPlugin, CAPBridgedPlugin {
125
134
  @objc func toggleBackButtonHandler(_ call: CAPPluginCall) {
126
135
  call.unimplemented()
127
136
  }
137
+
138
+ @objc func toggleEdgeGestureHandler(_ call: CAPPluginCall) {
139
+ DispatchQueue.main.async {
140
+ if call.getBool("enabled", false) {
141
+ self.loadGestureRecognizers()
142
+ } else {
143
+ self.destroyGestureRecognizers()
144
+ }
145
+
146
+ call.resolve()
147
+ }
148
+ }
149
+
150
+ @objc func handleEdgePan(_ recognizer: UIScreenEdgePanGestureRecognizer) {
151
+ guard let view = bridge?.webView else { return }
152
+
153
+ let translation = recognizer.translation(in: view)
154
+ let touch = recognizer.location(in: view)
155
+ let viewWidth = view.bounds.width
156
+ let viewHeight = view.bounds.height
157
+
158
+ var data: [String: Any] = [:]
159
+
160
+ data["touchX"] = touch.x
161
+ data["touchY"] = touch.y
162
+
163
+ switch recognizer.edges {
164
+ case .left:
165
+ let progress = translation.x / viewWidth
166
+ data["swipeEdge"] = "left"
167
+ data["progress"] = max(0, min(1, progress))
168
+ case .right:
169
+ let progress = -translation.x / viewWidth
170
+ data["swipeEdge"] = "right"
171
+ data["progress"] = max(0, min(1, progress))
172
+ default:
173
+ break
174
+ }
175
+
176
+ switch recognizer.state {
177
+ case .began:
178
+ data["phase"] = "start"
179
+ case .changed:
180
+ data["phase"] = "progress"
181
+ case .ended:
182
+ data["phase"] = "commit"
183
+ case .cancelled:
184
+ data["phase"] = "cancel"
185
+ case .failed:
186
+ data["phase"] = "cancel"
187
+ case .possible:
188
+ break
189
+ @unknown default:
190
+ break
191
+ }
192
+
193
+ // dont notify if there is no phase
194
+ guard data["phase"] != nil else { return }
195
+
196
+ if hasListeners("edgeGesture") {
197
+ notifyListeners("edgeGesture", data: data)
198
+ }
199
+ }
200
+
201
+ private func loadGestureRecognizers() {
202
+ guard self.leftEdgePanRecognizer == nil, self.rightEdgePanRecognizer == nil else { return }
203
+ guard let window = bridge?.viewController?.view.window else { return }
204
+
205
+ let leftEdgePanRecognizer = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(self.handleEdgePan(_:)))
206
+ leftEdgePanRecognizer.delegate = self
207
+ leftEdgePanRecognizer.edges = .left
208
+
209
+ let rightEdgePanRecognizer = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(self.handleEdgePan(_:)))
210
+ rightEdgePanRecognizer.delegate = self
211
+ rightEdgePanRecognizer.edges = .right
212
+
213
+ window.addGestureRecognizer(leftEdgePanRecognizer)
214
+ window.addGestureRecognizer(rightEdgePanRecognizer)
215
+
216
+ self.leftEdgePanRecognizer = leftEdgePanRecognizer
217
+ self.rightEdgePanRecognizer = rightEdgePanRecognizer
218
+ }
219
+
220
+ private func destroyGestureRecognizers() {
221
+ guard let leftEdgePanRecognizer = self.leftEdgePanRecognizer,
222
+ let rightEdgePanRecognizer = self.rightEdgePanRecognizer
223
+ else { return }
224
+
225
+ leftEdgePanRecognizer.view?.removeGestureRecognizer(leftEdgePanRecognizer)
226
+ rightEdgePanRecognizer.view?.removeGestureRecognizer(rightEdgePanRecognizer)
227
+
228
+ self.leftEdgePanRecognizer = nil
229
+ self.rightEdgePanRecognizer = nil
230
+ }
231
+ }
232
+
233
+ extension AppPlugin: UIGestureRecognizerDelegate {
234
+ public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
235
+ return gestureRecognizer === leftEdgePanRecognizer || gestureRecognizer === rightEdgePanRecognizer
236
+ }
128
237
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor/app",
3
- "version": "8.1.0",
3
+ "version": "8.1.1-dev-2542-20260611T172948.0",
4
4
  "description": "The App API handles high level App state and events.For example, this API emits events when the app enters and leaves the foreground, handles deeplinks, opens other apps, and manages persisted plugin state.",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -47,11 +47,11 @@
47
47
  "publish:cocoapod": "pod trunk push ./CapacitorApp.podspec --allow-warnings"
48
48
  },
49
49
  "devDependencies": {
50
- "@capacitor/android": "^8.0.0",
51
- "@capacitor/cli": "^8.0.0",
52
- "@capacitor/core": "^8.0.0",
50
+ "@capacitor/android": "next",
51
+ "@capacitor/cli": "next",
52
+ "@capacitor/core": "next",
53
53
  "@capacitor/docgen": "0.3.0",
54
- "@capacitor/ios": "^8.0.0",
54
+ "@capacitor/ios": "next",
55
55
  "@ionic/eslint-config": "^0.4.0",
56
56
  "@ionic/prettier-config": "^4.0.0",
57
57
  "@ionic/swiftlint-config": "^2.0.0",
@@ -64,7 +64,7 @@
64
64
  "typescript": "^5.9.3"
65
65
  },
66
66
  "peerDependencies": {
67
- "@capacitor/core": ">=8.0.0"
67
+ "@capacitor/core": ">=9.0.0-alpha.0"
68
68
  },
69
69
  "prettier": "@ionic/prettier-config",
70
70
  "swiftlint": "@ionic/swiftlint-config",
@@ -81,6 +81,5 @@
81
81
  },
82
82
  "publishConfig": {
83
83
  "access": "public"
84
- },
85
- "gitHead": "3678f5063762e8d9857ddb4f41aae5f65ead91fa"
84
+ }
86
85
  }