@capgo/capacitor-inappbrowser 8.18.1 → 8.20.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/README.md +126 -5
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/CapgoInAppBrowserPlugin.java +75 -3
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/FullscreenWindowState.java +72 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/Options.java +21 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +238 -21
- package/android/src/main/res/drawable/ic_fullscreen_exit.xml +10 -0
- package/android/src/main/res/layout/fullscreen_exit_button.xml +24 -0
- package/android/src/main/res/values/fullscreen_exit.xml +10 -0
- package/android/src/main/res/values/strings.xml +1 -0
- package/android/src/main/res/xml/fullscreen_exit_shape.xml +6 -0
- package/dist/docs.json +129 -1
- package/dist/esm/definitions.d.ts +78 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +9 -0
- package/dist/esm/web.js +11 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +11 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +11 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/InAppBrowserPlugin/BrowserFullscreenSupport.swift +178 -0
- package/ios/Sources/InAppBrowserPlugin/DownloadPreviewSupport.swift +28 -0
- package/ios/Sources/InAppBrowserPlugin/InAppBrowserPlugin.swift +90 -4
- package/ios/Sources/InAppBrowserPlugin/WKWebViewController.swift +40 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -217,7 +217,7 @@ All CCT options are Android-only and safely ignored on iOS. See [`OpenOptions`](
|
|
|
217
217
|
|
|
218
218
|
### Open WebView with Custom Dimensions
|
|
219
219
|
|
|
220
|
-
By default, the
|
|
220
|
+
By default, the WebView fills the available screen and retains its configured toolbar. You can set custom dimensions to control the size and position:
|
|
221
221
|
|
|
222
222
|
```js
|
|
223
223
|
import { InAppBrowser } from '@capgo/capacitor-inappbrowser';
|
|
@@ -259,9 +259,44 @@ InAppBrowser.openWebView({
|
|
|
259
259
|
|
|
260
260
|
Web platform is not supported. Use `window.open` instead.
|
|
261
261
|
|
|
262
|
-
###
|
|
262
|
+
### Fullscreen at launch and during a session
|
|
263
263
|
|
|
264
|
-
|
|
264
|
+
Set `fullscreen: true` to present a native WebView in fullscreen from its first visible frame:
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
import { InAppBrowser, ToolBarType } from '@capgo/capacitor-inappbrowser';
|
|
268
|
+
|
|
269
|
+
const listener = await InAppBrowser.addListener('fullscreenChange', ({ id, enabled }) => {
|
|
270
|
+
console.log('Fullscreen changed', id, enabled);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
const { id } = await InAppBrowser.openWebView({
|
|
274
|
+
url: 'https://example.com',
|
|
275
|
+
toolbarType: ToolBarType.NAVIGATION,
|
|
276
|
+
fullscreen: true,
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
await InAppBrowser.setFullscreen({ id, enabled: false });
|
|
280
|
+
await InAppBrowser.setFullscreen({ id, enabled: true });
|
|
281
|
+
const { enabled } = await InAppBrowser.getFullscreen({ id });
|
|
282
|
+
|
|
283
|
+
// When the host no longer needs updates:
|
|
284
|
+
await listener.remove();
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Fullscreen hides native navigation and system bars. A native exit button stays above the page at the top-right safe-area inset. Android Back exits fullscreen before navigating page history. Exiting restores the configured toolbar and safe-area settings. Entry and exit keep the same WebView, including its JavaScript state, cookies, and history.
|
|
288
|
+
|
|
289
|
+
The opening option defaults to `false`. It also works with `isPresentAfterPageLoad: true` and `hidden: true`. An initially hidden WebView applies fullscreen when first shown; until then, `getFullscreen()` reports `false` and the host's system bars stay unchanged. Calling `setFullscreen({ id, enabled: false })` cancels that pending startup request.
|
|
290
|
+
|
|
291
|
+
Backgrounding, hiding, closing, cross-origin navigation, and renderer termination exit fullscreen through native cleanup. Showing or resuming the WebView afterward does not enter fullscreen again. The host receives a `fullscreenChange` event for each applied change, including native exit controls. Register the listener before opening to observe initial entry.
|
|
292
|
+
|
|
293
|
+
These APIs control the browser's presentation independently of HTML/video fullscreen. They support full-size, frontmost `openWebView` presentations on iOS and Android. Runtime entry into a hidden WebView, custom dimensions, behind-host presentations, and missing target IDs reject. Web usage is unsupported. Permission prompts are the host application's responsibility.
|
|
294
|
+
|
|
295
|
+
The example app's Fullscreen section includes launch options and an interactive page for runtime entry, exit, hide/show, history, form, cookie, and counter checks.
|
|
296
|
+
|
|
297
|
+
### Extend content behind the status bar
|
|
298
|
+
|
|
299
|
+
To extend content behind the status bar, set `enabledSafeTopMargin` to `false`:
|
|
265
300
|
|
|
266
301
|
```js
|
|
267
302
|
import { InAppBrowser } from '@capgo/capacitor-inappbrowser';
|
|
@@ -277,7 +312,7 @@ This option works independently of the toolbar type:
|
|
|
277
312
|
- **iOS**: The webview extends behind the status bar, providing true edge-to-edge content
|
|
278
313
|
- **Android**: The top margin is disabled, allowing content to fill the entire screen
|
|
279
314
|
|
|
280
|
-
|
|
315
|
+
This setting controls the content inset. Use `fullscreen` to hide native navigation and system bars as well.
|
|
281
316
|
|
|
282
317
|
### Proxy examples
|
|
283
318
|
|
|
@@ -632,6 +667,7 @@ await InAppBrowser.openWebView({
|
|
|
632
667
|
* [`takeScreenshot(...)`](#takescreenshot)
|
|
633
668
|
* [`setUrl(...)`](#seturl)
|
|
634
669
|
* [`addListener('urlChangeEvent', ...)`](#addlistenerurlchangeevent-)
|
|
670
|
+
* [`addListener('fullscreenChange', ...)`](#addlistenerfullscreenchange-)
|
|
635
671
|
* [`addListener('buttonNearDoneClick', ...)`](#addlistenerbuttonneardoneclick-)
|
|
636
672
|
* [`addListener('closeEvent', ...)`](#addlistenercloseevent-)
|
|
637
673
|
* [`addListener('hideEvent', ...)`](#addlistenerhideevent-)
|
|
@@ -652,6 +688,8 @@ await InAppBrowser.openWebView({
|
|
|
652
688
|
* [`removeAllListeners()`](#removealllisteners)
|
|
653
689
|
* [`reload(...)`](#reload)
|
|
654
690
|
* [`updateDimensions(...)`](#updatedimensions)
|
|
691
|
+
* [`setFullscreen(...)`](#setfullscreen)
|
|
692
|
+
* [`getFullscreen(...)`](#getfullscreen)
|
|
655
693
|
* [`setEnabledSafeTopMargin(...)`](#setenabledsafetopmargin)
|
|
656
694
|
* [`setEnabledSafeBottomMargin(...)`](#setenabledsafebottommargin)
|
|
657
695
|
* [`openSecureWindow(...)`](#opensecurewindow)
|
|
@@ -1029,6 +1067,27 @@ Listen for url change, only for openWebView
|
|
|
1029
1067
|
--------------------
|
|
1030
1068
|
|
|
1031
1069
|
|
|
1070
|
+
### addListener('fullscreenChange', ...)
|
|
1071
|
+
|
|
1072
|
+
```typescript
|
|
1073
|
+
addListener(eventName: 'fullscreenChange', listenerFunc: (event: FullscreenChangeEvent) => void) => Promise<PluginListenerHandle>
|
|
1074
|
+
```
|
|
1075
|
+
|
|
1076
|
+
Listen for applied fullscreen changes, including startup entry, the native exit button,
|
|
1077
|
+
Android Back, and native lifecycle cleanup. Register before opening to observe startup entry.
|
|
1078
|
+
Repeated requests for the current state do not emit duplicate events.
|
|
1079
|
+
This event describes host-controlled fullscreen, not HTML/video fullscreen.
|
|
1080
|
+
|
|
1081
|
+
| Param | Type |
|
|
1082
|
+
| ------------------ | ------------------------------------------------------------------------------------------- |
|
|
1083
|
+
| **`eventName`** | <code>'fullscreenChange'</code> |
|
|
1084
|
+
| **`listenerFunc`** | <code>(event: <a href="#fullscreenchangeevent">FullscreenChangeEvent</a>) => void</code> |
|
|
1085
|
+
|
|
1086
|
+
**Returns:** <code>Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>></code>
|
|
1087
|
+
|
|
1088
|
+
--------------------
|
|
1089
|
+
|
|
1090
|
+
|
|
1032
1091
|
### addListener('buttonNearDoneClick', ...)
|
|
1033
1092
|
|
|
1034
1093
|
```typescript
|
|
@@ -1425,6 +1484,49 @@ When `id` is omitted, targets the active webview.
|
|
|
1425
1484
|
--------------------
|
|
1426
1485
|
|
|
1427
1486
|
|
|
1487
|
+
### setFullscreen(...)
|
|
1488
|
+
|
|
1489
|
+
```typescript
|
|
1490
|
+
setFullscreen(options: { enabled: boolean; id?: string; }) => Promise<void>
|
|
1491
|
+
```
|
|
1492
|
+
|
|
1493
|
+
Enter or exit immersive fullscreen without recreating or reloading the webview.
|
|
1494
|
+
When `id` is omitted, targets the active webview. Repeated calls are idempotent.
|
|
1495
|
+
Entry requires a visible, frontmost, full-size `openWebView` on iOS or Android.
|
|
1496
|
+
Missing webviews, invalid arguments, custom dimensions, behind-host presentations,
|
|
1497
|
+
and the Web platform reject. Use the opening `fullscreen` option for an initially hidden webview.
|
|
1498
|
+
Disabling also cancels any pending fullscreen-at-launch request.
|
|
1499
|
+
|
|
1500
|
+
Native exit controls, backgrounding, hiding, closing, cross-origin navigation, and renderer
|
|
1501
|
+
termination restore the original chrome even when host JavaScript cannot respond.
|
|
1502
|
+
|
|
1503
|
+
| Param | Type |
|
|
1504
|
+
| ------------- | ----------------------------------------------- |
|
|
1505
|
+
| **`options`** | <code>{ enabled: boolean; id?: string; }</code> |
|
|
1506
|
+
|
|
1507
|
+
--------------------
|
|
1508
|
+
|
|
1509
|
+
|
|
1510
|
+
### getFullscreen(...)
|
|
1511
|
+
|
|
1512
|
+
```typescript
|
|
1513
|
+
getFullscreen(options?: { id?: string | undefined; } | undefined) => Promise<{ enabled: boolean; }>
|
|
1514
|
+
```
|
|
1515
|
+
|
|
1516
|
+
Read the applied host-controlled fullscreen state of an `openWebView`.
|
|
1517
|
+
When `id` is omitted, targets the active webview. Initially hidden fullscreen webviews
|
|
1518
|
+
report `false` until their first presentation. Missing webviews and Web usage reject.
|
|
1519
|
+
HTML/video fullscreen does not change this value.
|
|
1520
|
+
|
|
1521
|
+
| Param | Type |
|
|
1522
|
+
| ------------- | ----------------------------- |
|
|
1523
|
+
| **`options`** | <code>{ id?: string; }</code> |
|
|
1524
|
+
|
|
1525
|
+
**Returns:** <code>Promise<{ enabled: boolean; }></code>
|
|
1526
|
+
|
|
1527
|
+
--------------------
|
|
1528
|
+
|
|
1529
|
+
|
|
1428
1530
|
### setEnabledSafeTopMargin(...)
|
|
1429
1531
|
|
|
1430
1532
|
```typescript
|
|
@@ -1574,6 +1676,7 @@ See the README section "openSecureWindow (OAuth)" for full setup examples.
|
|
|
1574
1676
|
|
|
1575
1677
|
| Prop | Type | Description | Default | Since |
|
|
1576
1678
|
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------ |
|
|
1679
|
+
| **`fullscreen`** | <code>boolean</code> | Present this webview in immersive fullscreen from its first visible frame. Hides native navigation and system bars and provides a native exit-fullscreen button. The same webview, page state, cookies, and history are retained on entry and exit. Exiting restores the configured toolbar and safe-area settings. Applies before presentation, including when `isPresentAfterPageLoad` is true. With `hidden: true`, waits for the first `show()` without changing the host's system bars. Subsequent hide/show or background/resume cycles do not re-enter fullscreen automatically. Only supported on iOS and Android for full-size, frontmost `openWebView` presentations. Custom dimensions and `toBack: true` are unsupported. The Web implementation rejects `true`. Permission prompts, if needed, are the host application's responsibility. | <code>false</code> | |
|
|
1577
1680
|
| **`url`** | <code>string</code> | Target URL to load. Remote `http://` and `https://` URLs are loaded as-is. To open bundled web assets from the app bundle without running a local HTTP server, pass a relative path such as `/index.html` or `assets/page.html`. The plugin resolves it to the Capacitor local URL for the current platform (defaults: `capacitor://localhost/...` on iOS, `https://localhost/...` on Android; actual scheme and host follow the app's configured Capacitor local URL) and serves files from the packaged `public/` directory, or `www/` on iOS when `public/` is absent. | | 0.1.0 |
|
|
1578
1681
|
| **`headers`** | <code><a href="#headers">Headers</a></code> | <a href="#headers">Headers</a> to send with the request. | | 0.1.0 |
|
|
1579
1682
|
| **`customUserAgent`** | <code>string</code> | Custom User-Agent string for the webview. When set, replaces the system default webview User-Agent on iOS and Android. Takes precedence over a `User-Agent` entry in `headers`. | | 8.13.0 |
|
|
@@ -1590,7 +1693,8 @@ See the README section "openSecureWindow (OAuth)" for full setup examples.
|
|
|
1590
1693
|
| **`useSharedDataStore`** | <code>boolean</code> | Share the host Capacitor WebView's website data store (cookies, local storage, etc.). On iOS 17+, InAppBrowser uses an isolated plugin-owned `WKWebsiteDataStore` by default so host and browser data stay separate. Set this to `true` to use `WKWebsiteDataStore.default()` instead, which shares session cookies with the Capacitor host WebView. Useful for SSO / OIDC silent login when the IdP session was established in the main app WebView. Requires `persistWebViewData: true` (the default). When `persistWebViewData` is false, a non-persistent store is used and this option has no effect. On Android this is a no-op: cookies are already process-global via `CookieManager`. On Web this is a no-op. Warning: clearing cookies/cache for a webview opened with this flag can affect the host WebView on iOS, because both share the same store. `clearAllBrowsingData()` still skips the host store. | <code>false</code> | 8.13.6 |
|
|
1591
1694
|
| **`clientCertificate`** | <code>'none' \| 'prompt'</code> | Controls Android TLS client certificate prompts during HTTPS handshakes. Use `prompt` to show the system certificate picker; omit or use `none` to cancel silently (default). | <code>"none"</code> | 8.7.5 |
|
|
1592
1695
|
| **`clientCertificatePrompt`** | <code>boolean</code> | | | |
|
|
1593
|
-
| **`handleDownloads`** | <code>boolean</code> | Automatically handles downloads triggered inside the webview without requiring a custom JavaScript bridge. When enabled: - Standard attachment responses are written to a temporary file. - `blob:` downloads are also captured when the platform supports them. - Previewable files reopen inside the in-app browser when possible. - Other files are handed off to the native preview or viewer flow. - `downloadCompleted` and `downloadFailed` events notify the host app about the saved file.
|
|
1696
|
+
| **`handleDownloads`** | <code>boolean</code> | Automatically handles downloads triggered inside the webview without requiring a custom JavaScript bridge. When enabled: - Standard attachment responses are written to a temporary file. - `blob:` downloads are also captured when the platform supports them. - Previewable files reopen inside the in-app browser when possible (see `downloadPreview`). - Other files are handed off to the native preview or viewer flow. - `downloadCompleted` and `downloadFailed` events notify the host app about the saved file. | <code>false</code> | 8.6.0 |
|
|
1697
|
+
| **`downloadPreview`** | <code><a href="#downloadpreview">DownloadPreview</a></code> | Controls where managed downloads are previewed after saving. - `'inAppBrowser'` (default): Reopens previewable files (PDF, images, text, JSON) inside the same webview. - `'systemPreview'`: Opens the system Quick Look preview with share and Save to Files actions. iOS only; ignored on Android. Requires `handleDownloads: true`. | <code>"inAppBrowser"</code> | 8.19.0 |
|
|
1594
1698
|
| **`shareDisclaimer`** | <code><a href="#disclaimeroptions">DisclaimerOptions</a></code> | Share options for the webview. When provided, shows a disclaimer dialog before sharing content. This is useful for: - Warning users about sharing sensitive information - Getting user consent before sharing - Explaining what will be shared - Complying with privacy regulations Note: shareSubject is required when using shareDisclaimer | | 0.1.0 |
|
|
1595
1699
|
| **`toolbarType`** | <code><a href="#toolbartype">ToolBarType</a></code> | Toolbar type determines the appearance and behavior of the browser's toolbar - "activity": Shows a simple toolbar with just a close button and share button - "navigation": Shows a full navigation toolbar with back/forward buttons - "blank": Shows no toolbar - "": Default toolbar with close button | <code>ToolBarType.DEFAULT</code> | 0.1.0 |
|
|
1596
1700
|
| **`shareSubject`** | <code>string</code> | Subject text for sharing. Required when using shareDisclaimer. This text will be used as the subject line when sharing content. | | 0.1.0 |
|
|
@@ -1725,6 +1829,16 @@ Any regex property that is omitted is treated as a wildcard.
|
|
|
1725
1829
|
| **`url`** | <code>string</code> | Emit when the url changes | 0.0.1 |
|
|
1726
1830
|
|
|
1727
1831
|
|
|
1832
|
+
#### FullscreenChangeEvent
|
|
1833
|
+
|
|
1834
|
+
A change to host-controlled fullscreen; independent of HTML/video fullscreen.
|
|
1835
|
+
|
|
1836
|
+
| Prop | Type | Description |
|
|
1837
|
+
| ------------- | -------------------- | --------------------------------------------------------------- |
|
|
1838
|
+
| **`id`** | <code>string</code> | Webview instance id. |
|
|
1839
|
+
| **`enabled`** | <code>boolean</code> | Whether fullscreen is currently applied to the visible webview. |
|
|
1840
|
+
|
|
1841
|
+
|
|
1728
1842
|
#### ButtonNearDoneEvent
|
|
1729
1843
|
|
|
1730
1844
|
| Prop | Type | Description | Since |
|
|
@@ -1956,6 +2070,13 @@ Construct a type with a set of properties K of type T
|
|
|
1956
2070
|
<code>'click' | 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel'</code>
|
|
1957
2071
|
|
|
1958
2072
|
|
|
2073
|
+
#### DownloadPreview
|
|
2074
|
+
|
|
2075
|
+
Where managed downloads are previewed after saving.
|
|
2076
|
+
|
|
2077
|
+
<code>'inAppBrowser' | 'systemPreview'</code>
|
|
2078
|
+
|
|
2079
|
+
|
|
1959
2080
|
#### PreferredContentMode
|
|
1960
2081
|
|
|
1961
2082
|
Web content rendering mode for managed WKWebViews on iOS.
|
|
@@ -339,6 +339,7 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
|
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
private WebViewDialog createManagedDialog(String webViewId, Options options, boolean makeActive) {
|
|
342
|
+
if (fullscreenPaused) options.setFullscreen(false);
|
|
342
343
|
WebViewDialog dialog = new WebViewDialog(
|
|
343
344
|
getContext(),
|
|
344
345
|
android.R.style.Theme_NoTitleBar,
|
|
@@ -346,6 +347,12 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
|
|
|
346
347
|
CapgoInAppBrowserPlugin.this,
|
|
347
348
|
getBridge().getWebView()
|
|
348
349
|
);
|
|
350
|
+
dialog.setFullscreenChangeListener((enabled) -> {
|
|
351
|
+
JSObject event = new JSObject();
|
|
352
|
+
event.put("id", webViewId);
|
|
353
|
+
event.put("enabled", enabled);
|
|
354
|
+
notifyListeners("fullscreenChange", event);
|
|
355
|
+
});
|
|
349
356
|
dialog.setInstanceId(webViewId);
|
|
350
357
|
dialog.activity = CapgoInAppBrowserPlugin.this.getActivity();
|
|
351
358
|
dialog.bindToHostActivity();
|
|
@@ -1117,6 +1124,18 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
|
|
|
1117
1124
|
options.setAllowScreenshotsFromWebPage(Boolean.TRUE.equals(call.getBoolean("allowScreenshotsFromWebPage", false)));
|
|
1118
1125
|
options.setCaptureConsoleLogs(Boolean.TRUE.equals(call.getBoolean("captureConsoleLogs", false)));
|
|
1119
1126
|
options.setHandleDownloads(Boolean.TRUE.equals(call.getBoolean("handleDownloads", false)));
|
|
1127
|
+
String downloadPreview = call.getString("downloadPreview", "inAppBrowser");
|
|
1128
|
+
if (downloadPreview != null) {
|
|
1129
|
+
String normalizedDownloadPreview = downloadPreview.toLowerCase(Locale.ROOT);
|
|
1130
|
+
if ("inappbrowser".equals(normalizedDownloadPreview)) {
|
|
1131
|
+
options.setDownloadPreview("inAppBrowser");
|
|
1132
|
+
} else if ("systempreview".equals(normalizedDownloadPreview)) {
|
|
1133
|
+
options.setDownloadPreview("systemPreview");
|
|
1134
|
+
} else {
|
|
1135
|
+
call.reject("downloadPreview must be 'inAppBrowser' or 'systemPreview'");
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1120
1139
|
|
|
1121
1140
|
options.setPersistWebViewData(call.getBoolean("persistWebViewData", true));
|
|
1122
1141
|
options.setClearCookiesOnOpen(Boolean.TRUE.equals(call.getBoolean("clearCookiesOnOpen", false)));
|
|
@@ -1355,9 +1374,14 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
|
|
|
1355
1374
|
options.setY(y);
|
|
1356
1375
|
}
|
|
1357
1376
|
|
|
1377
|
+
options.setFullscreen(Boolean.TRUE.equals(call.getBoolean("fullscreen", false)));
|
|
1358
1378
|
options.setHidden(Boolean.TRUE.equals(call.getBoolean("hidden", false)));
|
|
1359
1379
|
options.setToBack(Boolean.TRUE.equals(call.getBoolean("toBack", false)));
|
|
1360
1380
|
options.setTransparentBackground(call.getBoolean("transparentBackground", true));
|
|
1381
|
+
if (options.isFullscreen() && (options.isToBack() || width != null || height != null || x != null || y != null)) {
|
|
1382
|
+
call.reject("Fullscreen requires a full-size front WebView");
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1361
1385
|
boolean allowWebViewJsVisibilityControl = getConfig().getBoolean("allowWebViewJsVisibilityControl", false);
|
|
1362
1386
|
options.setAllowWebViewJsVisibilityControl(allowWebViewJsVisibilityControl);
|
|
1363
1387
|
options.setInvisibilityMode(Options.InvisibilityMode.fromString(call.getString("invisibilityMode", "AWARE")));
|
|
@@ -1448,6 +1472,50 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
|
|
|
1448
1472
|
);
|
|
1449
1473
|
}
|
|
1450
1474
|
|
|
1475
|
+
private boolean fullscreenPaused;
|
|
1476
|
+
|
|
1477
|
+
@PluginMethod
|
|
1478
|
+
public void setFullscreen(PluginCall call) {
|
|
1479
|
+
Object enabled = call.getData().opt("enabled");
|
|
1480
|
+
if (!(enabled instanceof Boolean)) {
|
|
1481
|
+
call.reject("enabled must be a boolean");
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1484
|
+
String id = resolveTargetId(call);
|
|
1485
|
+
getActivity().runOnUiThread(() -> {
|
|
1486
|
+
WebViewDialog dialog = resolveDialog(id);
|
|
1487
|
+
if (dialog == null) {
|
|
1488
|
+
call.reject("WebView is not initialized");
|
|
1489
|
+
return;
|
|
1490
|
+
}
|
|
1491
|
+
if ((Boolean) enabled && (!dialog.isShowing() || fullscreenPaused)) {
|
|
1492
|
+
call.reject("Application is in background");
|
|
1493
|
+
return;
|
|
1494
|
+
}
|
|
1495
|
+
try {
|
|
1496
|
+
dialog.setFullscreen((Boolean) enabled);
|
|
1497
|
+
call.resolve();
|
|
1498
|
+
} catch (IllegalStateException error) {
|
|
1499
|
+
call.reject(error.getMessage());
|
|
1500
|
+
}
|
|
1501
|
+
});
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
@PluginMethod
|
|
1505
|
+
public void getFullscreen(PluginCall call) {
|
|
1506
|
+
String id = resolveTargetId(call);
|
|
1507
|
+
getActivity().runOnUiThread(() -> {
|
|
1508
|
+
WebViewDialog dialog = resolveDialog(id);
|
|
1509
|
+
if (dialog == null) {
|
|
1510
|
+
call.reject("WebView is not initialized");
|
|
1511
|
+
return;
|
|
1512
|
+
}
|
|
1513
|
+
JSObject result = new JSObject();
|
|
1514
|
+
result.put("enabled", dialog.isFullscreen());
|
|
1515
|
+
call.resolve(result);
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1451
1519
|
@PluginMethod
|
|
1452
1520
|
public void hide(PluginCall call) {
|
|
1453
1521
|
String targetId = resolveTargetId(call);
|
|
@@ -1466,6 +1534,7 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
|
|
|
1466
1534
|
call.reject("WebView is not initialized");
|
|
1467
1535
|
return;
|
|
1468
1536
|
}
|
|
1537
|
+
dialog.clearFullscreen();
|
|
1469
1538
|
dialog.setHidden(true);
|
|
1470
1539
|
call.resolve();
|
|
1471
1540
|
}
|
|
@@ -1491,6 +1560,9 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
|
|
|
1491
1560
|
call.reject("WebView is not initialized");
|
|
1492
1561
|
return;
|
|
1493
1562
|
}
|
|
1563
|
+
if (dialog.getInstanceId() != null) {
|
|
1564
|
+
setActiveWebView(dialog.getInstanceId(), dialog);
|
|
1565
|
+
}
|
|
1494
1566
|
dialog.setHidden(false);
|
|
1495
1567
|
Options options = dialog.getOptions();
|
|
1496
1568
|
if (options != null && options.isToBack()) {
|
|
@@ -1501,9 +1573,6 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
|
|
|
1501
1573
|
} else {
|
|
1502
1574
|
dialog.bringToFrontLayer();
|
|
1503
1575
|
}
|
|
1504
|
-
if (dialog.getInstanceId() != null) {
|
|
1505
|
-
setActiveWebView(dialog.getInstanceId(), dialog);
|
|
1506
|
-
}
|
|
1507
1576
|
call.resolve();
|
|
1508
1577
|
}
|
|
1509
1578
|
}
|
|
@@ -1886,6 +1955,7 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
|
|
|
1886
1955
|
}
|
|
1887
1956
|
|
|
1888
1957
|
protected void handleOnResume() {
|
|
1958
|
+
fullscreenPaused = false;
|
|
1889
1959
|
customTabsLifecycleSupport.onResume(customTabsBinder);
|
|
1890
1960
|
|
|
1891
1961
|
// If we have a saved call and user returned without callback, reject
|
|
@@ -1896,6 +1966,8 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
|
|
|
1896
1966
|
}
|
|
1897
1967
|
|
|
1898
1968
|
protected void handleOnPause() {
|
|
1969
|
+
fullscreenPaused = true;
|
|
1970
|
+
for (WebViewDialog dialog : webViewDialogs.values()) dialog.clearFullscreen();
|
|
1899
1971
|
customTabsLifecycleSupport.onPause(customTabsBinder);
|
|
1900
1972
|
}
|
|
1901
1973
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
package ee.forgr.capacitor_inappbrowser;
|
|
2
|
+
|
|
3
|
+
import android.os.Build;
|
|
4
|
+
import android.view.View;
|
|
5
|
+
import android.view.Window;
|
|
6
|
+
import android.view.WindowManager;
|
|
7
|
+
import androidx.core.view.ViewCompat;
|
|
8
|
+
import androidx.core.view.WindowInsetsCompat;
|
|
9
|
+
import androidx.core.view.WindowInsetsControllerCompat;
|
|
10
|
+
|
|
11
|
+
/** Saves each nesting level so media fullscreen can return to browser fullscreen. */
|
|
12
|
+
final class FullscreenWindowState {
|
|
13
|
+
|
|
14
|
+
private final Window window;
|
|
15
|
+
private final WindowManager.LayoutParams attributes = new WindowManager.LayoutParams();
|
|
16
|
+
private final int visibility;
|
|
17
|
+
private final int behavior;
|
|
18
|
+
private final boolean statusVisible;
|
|
19
|
+
private final boolean navigationVisible;
|
|
20
|
+
|
|
21
|
+
FullscreenWindowState(Window window) {
|
|
22
|
+
this.window = window;
|
|
23
|
+
attributes.copyFrom(window.getAttributes());
|
|
24
|
+
View decor = window.getDecorView();
|
|
25
|
+
visibility = decor.getSystemUiVisibility();
|
|
26
|
+
WindowInsetsControllerCompat controller = new WindowInsetsControllerCompat(window, decor);
|
|
27
|
+
behavior = controller.getSystemBarsBehavior();
|
|
28
|
+
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(decor);
|
|
29
|
+
statusVisible =
|
|
30
|
+
insets != null
|
|
31
|
+
? insets.isVisible(WindowInsetsCompat.Type.statusBars())
|
|
32
|
+
: (attributes.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0;
|
|
33
|
+
navigationVisible =
|
|
34
|
+
insets != null
|
|
35
|
+
? insets.isVisible(WindowInsetsCompat.Type.navigationBars())
|
|
36
|
+
: (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
void enter() {
|
|
40
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
41
|
+
// DEFAULT excludes the cutout once bars hide, leaving a black band in immersive mode.
|
|
42
|
+
WindowManager.LayoutParams fullscreenAttributes = window.getAttributes();
|
|
43
|
+
fullscreenAttributes.layoutInDisplayCutoutMode =
|
|
44
|
+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
|
|
45
|
+
? WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
|
|
46
|
+
: WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
|
47
|
+
window.setAttributes(fullscreenAttributes);
|
|
48
|
+
}
|
|
49
|
+
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
|
50
|
+
View decor = window.getDecorView();
|
|
51
|
+
decor.setSystemUiVisibility(
|
|
52
|
+
decor.getSystemUiVisibility() |
|
|
53
|
+
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
|
54
|
+
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
|
55
|
+
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
|
56
|
+
);
|
|
57
|
+
WindowInsetsControllerCompat controller = new WindowInsetsControllerCompat(window, decor);
|
|
58
|
+
controller.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
|
59
|
+
controller.hide(WindowInsetsCompat.Type.systemBars());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void restore() {
|
|
63
|
+
WindowInsetsControllerCompat controller = new WindowInsetsControllerCompat(window, window.getDecorView());
|
|
64
|
+
if (statusVisible) controller.show(WindowInsetsCompat.Type.statusBars());
|
|
65
|
+
else controller.hide(WindowInsetsCompat.Type.statusBars());
|
|
66
|
+
if (navigationVisible) controller.show(WindowInsetsCompat.Type.navigationBars());
|
|
67
|
+
else controller.hide(WindowInsetsCompat.Type.navigationBars());
|
|
68
|
+
controller.setSystemBarsBehavior(behavior);
|
|
69
|
+
window.setAttributes(attributes);
|
|
70
|
+
window.getDecorView().setSystemUiVisibility(visibility);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -198,12 +198,24 @@ public class Options {
|
|
|
198
198
|
private boolean hidden = false;
|
|
199
199
|
private boolean toBack = false;
|
|
200
200
|
private boolean transparentBackground = true;
|
|
201
|
+
private boolean fullscreen = false;
|
|
202
|
+
|
|
203
|
+
public boolean isFullscreen() {
|
|
204
|
+
return fullscreen;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public void setFullscreen(boolean fullscreen) {
|
|
208
|
+
this.fullscreen = fullscreen;
|
|
209
|
+
}
|
|
210
|
+
|
|
201
211
|
private boolean showScreenshotButton = false;
|
|
202
212
|
private boolean screenshotOnHide = false;
|
|
203
213
|
private boolean allowWebViewJsVisibilityControl = false;
|
|
204
214
|
private boolean allowScreenshotsFromWebPage = false;
|
|
205
215
|
private boolean captureConsoleLogs = false;
|
|
206
216
|
private boolean handleDownloads = false;
|
|
217
|
+
/** Accepted for API parity with iOS; Android already uses an external viewer for managed downloads. */
|
|
218
|
+
private String downloadPreview = "inAppBrowser";
|
|
207
219
|
private boolean persistWebViewData = true;
|
|
208
220
|
private boolean clearCookiesOnOpen = false;
|
|
209
221
|
private boolean clearCacheOnOpen = false;
|
|
@@ -315,6 +327,14 @@ public class Options {
|
|
|
315
327
|
this.handleDownloads = handleDownloads;
|
|
316
328
|
}
|
|
317
329
|
|
|
330
|
+
public String getDownloadPreview() {
|
|
331
|
+
return downloadPreview;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
public void setDownloadPreview(String downloadPreview) {
|
|
335
|
+
this.downloadPreview = downloadPreview;
|
|
336
|
+
}
|
|
337
|
+
|
|
318
338
|
public boolean getPersistWebViewData() {
|
|
319
339
|
return persistWebViewData;
|
|
320
340
|
}
|
|
@@ -900,6 +920,7 @@ public class Options {
|
|
|
900
920
|
copy.setAllowScreenshotsFromWebPage(allowScreenshotsFromWebPage);
|
|
901
921
|
copy.setCaptureConsoleLogs(captureConsoleLogs);
|
|
902
922
|
copy.setHandleDownloads(handleDownloads);
|
|
923
|
+
copy.setDownloadPreview(downloadPreview);
|
|
903
924
|
copy.setInvisibilityMode(invisibilityMode);
|
|
904
925
|
copy.setPopupWindowMode(true);
|
|
905
926
|
copy.setHiddenPopupWindow(hiddenPopupWindow);
|