@capgo/inappbrowser 6.6.8 → 6.8.1
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 +49 -26
- package/android/build.gradle +1 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/InAppBrowserPlugin.java +28 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/Options.java +110 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewCallbacks.java +2 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +78 -2
- package/android/src/main/res/layout/tool_bar.xml +13 -0
- package/android/src/main/res/values/strings.xml +1 -0
- package/dist/docs.json +49 -0
- package/dist/esm/definitions.d.ts +19 -0
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Plugin/InAppBrowserPlugin.swift +42 -2
- package/ios/Plugin/WKWebViewController.swift +52 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,6 +84,7 @@ Add the following to your `Info.plist` file:
|
|
|
84
84
|
* [`postMessage(...)`](#postmessage)
|
|
85
85
|
* [`setUrl(...)`](#seturl)
|
|
86
86
|
* [`addListener('urlChangeEvent', ...)`](#addlistenerurlchangeevent-)
|
|
87
|
+
* [`addListener('buttonNearDoneClick', ...)`](#addlistenerbuttonneardoneclick-)
|
|
87
88
|
* [`addListener('closeEvent', ...)`](#addlistenercloseevent-)
|
|
88
89
|
* [`addListener('confirmBtnClicked', ...)`](#addlistenerconfirmbtnclicked-)
|
|
89
90
|
* [`addListener('messageFromWebview', ...)`](#addlistenermessagefromwebview-)
|
|
@@ -286,6 +287,22 @@ Listen for url change, only for openWebView
|
|
|
286
287
|
--------------------
|
|
287
288
|
|
|
288
289
|
|
|
290
|
+
### addListener('buttonNearDoneClick', ...)
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
addListener(eventName: "buttonNearDoneClick", listenerFunc: ButtonNearListener) => Promise<PluginListenerHandle>
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
| Param | Type |
|
|
297
|
+
| ------------------ | ----------------------------------------------------------------- |
|
|
298
|
+
| **`eventName`** | <code>'buttonNearDoneClick'</code> |
|
|
299
|
+
| **`listenerFunc`** | <code><a href="#buttonnearlistener">ButtonNearListener</a></code> |
|
|
300
|
+
|
|
301
|
+
**Returns:** <code>Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>></code>
|
|
302
|
+
|
|
303
|
+
--------------------
|
|
304
|
+
|
|
305
|
+
|
|
289
306
|
### addListener('closeEvent', ...)
|
|
290
307
|
|
|
291
308
|
```typescript
|
|
@@ -463,32 +480,33 @@ Reload the current web page.
|
|
|
463
480
|
|
|
464
481
|
#### OpenWebViewOptions
|
|
465
482
|
|
|
466
|
-
| Prop | Type
|
|
467
|
-
| -------------------------------------- |
|
|
468
|
-
| **`url`** | <code>string</code>
|
|
469
|
-
| **`headers`** | <code><a href="#headers">Headers</a></code>
|
|
470
|
-
| **`credentials`** | <code><a href="#credentials">Credentials</a></code>
|
|
471
|
-
| **`shareDisclaimer`** | <code><a href="#disclaimeroptions">DisclaimerOptions</a></code>
|
|
472
|
-
| **`toolbarType`** | <code><a href="#toolbartype">ToolBarType</a></code>
|
|
473
|
-
| **`shareSubject`** | <code>string</code>
|
|
474
|
-
| **`title`** | <code>string</code>
|
|
475
|
-
| **`backgroundColor`** | <code><a href="#backgroundcolor">BackgroundColor</a></code>
|
|
476
|
-
| **`activeNativeNavigationForWebview`** | <code>boolean</code>
|
|
477
|
-
| **`disableGoBackOnNativeApplication`** | <code>boolean</code>
|
|
478
|
-
| **`isPresentAfterPageLoad`** | <code>boolean</code>
|
|
479
|
-
| **`isInspectable`** | <code>boolean</code>
|
|
480
|
-
| **`isAnimated`** | <code>boolean</code>
|
|
481
|
-
| **`showReloadButton`** | <code>boolean</code>
|
|
482
|
-
| **`closeModal`** | <code>boolean</code>
|
|
483
|
-
| **`closeModalTitle`** | <code>string</code>
|
|
484
|
-
| **`closeModalDescription`** | <code>string</code>
|
|
485
|
-
| **`closeModalOk`** | <code>string</code>
|
|
486
|
-
| **`closeModalCancel`** | <code>string</code>
|
|
487
|
-
| **`visibleTitle`** | <code>boolean</code>
|
|
488
|
-
| **`toolbarColor`** | <code>string</code>
|
|
489
|
-
| **`showArrow`** | <code>boolean</code>
|
|
490
|
-
| **`ignoreUntrustedSSLError`** | <code>boolean</code>
|
|
491
|
-
| **`preShowScript`** | <code><a href="#string">String</a></code>
|
|
483
|
+
| Prop | Type | Description | Default | Since |
|
|
484
|
+
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ------ |
|
|
485
|
+
| **`url`** | <code>string</code> | Target URL to load. | | 0.1.0 |
|
|
486
|
+
| **`headers`** | <code><a href="#headers">Headers</a></code> | <a href="#headers">Headers</a> to send with the request. | | 0.1.0 |
|
|
487
|
+
| **`credentials`** | <code><a href="#credentials">Credentials</a></code> | <a href="#credentials">Credentials</a> to send with the request and all subsequent requests for the same host. | | 6.1.0 |
|
|
488
|
+
| **`shareDisclaimer`** | <code><a href="#disclaimeroptions">DisclaimerOptions</a></code> | share options | | 0.1.0 |
|
|
489
|
+
| **`toolbarType`** | <code><a href="#toolbartype">ToolBarType</a></code> | Toolbar type | <code>ToolBarType.DEFAULT</code> | 0.1.0 |
|
|
490
|
+
| **`shareSubject`** | <code>string</code> | Share subject | | 0.1.0 |
|
|
491
|
+
| **`title`** | <code>string</code> | Title of the browser | <code>'New Window'</code> | 0.1.0 |
|
|
492
|
+
| **`backgroundColor`** | <code><a href="#backgroundcolor">BackgroundColor</a></code> | Background color of the browser, only on IOS | <code>BackgroundColor.BLACK</code> | 0.1.0 |
|
|
493
|
+
| **`activeNativeNavigationForWebview`** | <code>boolean</code> | If true, active the native navigation within the webview, Android only | <code>false</code> | |
|
|
494
|
+
| **`disableGoBackOnNativeApplication`** | <code>boolean</code> | Disable the possibility to go back on native application, usefull to force user to stay on the webview, Android only | <code>false</code> | |
|
|
495
|
+
| **`isPresentAfterPageLoad`** | <code>boolean</code> | Open url in a new window fullscreen isPresentAfterPageLoad: if true, the browser will be presented after the page is loaded, if false, the browser will be presented immediately. | <code>false</code> | 0.1.0 |
|
|
496
|
+
| **`isInspectable`** | <code>boolean</code> | Whether the website in the webview is inspectable or not, ios only | <code>false</code> | |
|
|
497
|
+
| **`isAnimated`** | <code>boolean</code> | Whether the webview opening is animated or not, ios only | <code>true</code> | |
|
|
498
|
+
| **`showReloadButton`** | <code>boolean</code> | Shows a reload button that reloads the web page | <code>false</code> | 1.0.15 |
|
|
499
|
+
| **`closeModal`** | <code>boolean</code> | CloseModal: if true a confirm will be displayed when user clicks on close button, if false the browser will be closed immediately. | <code>false</code> | 1.1.0 |
|
|
500
|
+
| **`closeModalTitle`** | <code>string</code> | CloseModalTitle: title of the confirm when user clicks on close button, only on IOS | <code>'Close'</code> | 1.1.0 |
|
|
501
|
+
| **`closeModalDescription`** | <code>string</code> | CloseModalDescription: description of the confirm when user clicks on close button, only on IOS | <code>'Are you sure you want to close this window?'</code> | 1.1.0 |
|
|
502
|
+
| **`closeModalOk`** | <code>string</code> | CloseModalOk: text of the confirm button when user clicks on close button, only on IOS | <code>'Close'</code> | 1.1.0 |
|
|
503
|
+
| **`closeModalCancel`** | <code>string</code> | CloseModalCancel: text of the cancel button when user clicks on close button, only on IOS | <code>'Cancel'</code> | 1.1.0 |
|
|
504
|
+
| **`visibleTitle`** | <code>boolean</code> | visibleTitle: if true the website title would be shown else shown empty | <code>true</code> | 1.2.5 |
|
|
505
|
+
| **`toolbarColor`** | <code>string</code> | toolbarColor: color of the toolbar in hex format | <code>'#ffffff''</code> | 1.2.5 |
|
|
506
|
+
| **`showArrow`** | <code>boolean</code> | showArrow: if true an arrow would be shown instead of cross for closing the window | <code>false</code> | 1.2.5 |
|
|
507
|
+
| **`ignoreUntrustedSSLError`** | <code>boolean</code> | ignoreUntrustedSSLError: if true, the webview will ignore untrusted SSL errors allowing the user to view the website. | <code>false</code> | 6.1.0 |
|
|
508
|
+
| **`preShowScript`** | <code><a href="#string">String</a></code> | preShowScript: if isPresentAfterPageLoad is true and this variable is set the plugin will inject a script before showing the browser. This script will be run in an async context. The plugin will wait for the script to finish (max 10 seconds) | | 6.6.0 |
|
|
509
|
+
| **`buttonNearDone`** | <code>{ ios: { iconType: 'sf-symbol' \| 'asset'; icon: <a href="#string">String</a>; }; android: { iconType: 'asset'; icon: <a href="#string">String</a>; width?: number; height?: number; }; }</code> | buttonNearDone allows for a creation of a custom button. Please see [buttonNearDone.md](/buttonNearDone.md) for more info. | | 6.7.0 |
|
|
492
510
|
|
|
493
511
|
|
|
494
512
|
#### DisclaimerOptions
|
|
@@ -634,6 +652,11 @@ Construct a type with a set of properties K of type T
|
|
|
634
652
|
<code>(state: <a href="#urlevent">UrlEvent</a>): void</code>
|
|
635
653
|
|
|
636
654
|
|
|
655
|
+
#### ButtonNearListener
|
|
656
|
+
|
|
657
|
+
<code>(state: {}): void</code>
|
|
658
|
+
|
|
659
|
+
|
|
637
660
|
#### ConfirmBtnListener
|
|
638
661
|
|
|
639
662
|
<code>(state: <a href="#btnevent">BtnEvent</a>): void</code>
|
package/android/build.gradle
CHANGED
|
@@ -52,6 +52,7 @@ repositories {
|
|
|
52
52
|
dependencies {
|
|
53
53
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
54
54
|
implementation project(':capacitor-android')
|
|
55
|
+
implementation 'com.caverock:androidsvg:1.4'
|
|
55
56
|
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
56
57
|
testImplementation "junit:junit:$junitVersion"
|
|
57
58
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
@@ -425,6 +425,29 @@ public class InAppBrowserPlugin
|
|
|
425
425
|
options.setIgnoreUntrustedSSLError(
|
|
426
426
|
Boolean.TRUE.equals(call.getBoolean("ignoreUntrustedSSLError", false))
|
|
427
427
|
);
|
|
428
|
+
|
|
429
|
+
try {
|
|
430
|
+
Options.ButtonNearDone buttonNearDone =
|
|
431
|
+
Options.ButtonNearDone.generateFromPluginCall(
|
|
432
|
+
call,
|
|
433
|
+
getActivity().getAssets()
|
|
434
|
+
);
|
|
435
|
+
options.setButtonNearDone(buttonNearDone);
|
|
436
|
+
} catch (IllegalArgumentException illegalArgumentException) {
|
|
437
|
+
call.reject(
|
|
438
|
+
String.format(
|
|
439
|
+
"ButtonNearDone rejected: %s",
|
|
440
|
+
illegalArgumentException.getMessage()
|
|
441
|
+
)
|
|
442
|
+
);
|
|
443
|
+
} catch (RuntimeException e) {
|
|
444
|
+
Log.e(
|
|
445
|
+
"WebViewDialog",
|
|
446
|
+
String.format("ButtonNearDone runtime error: %s", e)
|
|
447
|
+
);
|
|
448
|
+
call.reject(String.format("ButtonNearDone RuntimeException: %s", e));
|
|
449
|
+
}
|
|
450
|
+
|
|
428
451
|
options.setShareDisclaimer(call.getObject("shareDisclaimer", null));
|
|
429
452
|
options.setPreShowScript(call.getString("preShowScript", null));
|
|
430
453
|
options.setShareSubject(call.getString("shareSubject", null));
|
|
@@ -477,6 +500,11 @@ public class InAppBrowserPlugin
|
|
|
477
500
|
notifyListeners("pageLoadError", new JSObject());
|
|
478
501
|
}
|
|
479
502
|
|
|
503
|
+
@Override
|
|
504
|
+
public void buttonNearDoneClicked() {
|
|
505
|
+
notifyListeners("buttonNearDoneClick", new JSObject());
|
|
506
|
+
}
|
|
507
|
+
|
|
480
508
|
@Override
|
|
481
509
|
public void javascriptCallback(String message) {
|
|
482
510
|
// Handle the message received from JavaScript
|
|
@@ -1,15 +1,117 @@
|
|
|
1
1
|
package ee.forgr.capacitor_inappbrowser;
|
|
2
2
|
|
|
3
|
+
import android.content.res.AssetManager;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
3
5
|
import com.getcapacitor.JSObject;
|
|
4
6
|
import com.getcapacitor.PluginCall;
|
|
7
|
+
import java.io.IOException;
|
|
8
|
+
import java.io.InputStream;
|
|
9
|
+
import java.util.Objects;
|
|
5
10
|
|
|
6
11
|
public class Options {
|
|
7
12
|
|
|
13
|
+
public static class ButtonNearDone {
|
|
14
|
+
|
|
15
|
+
public enum AllIconTypes {
|
|
16
|
+
ASSET,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private AllIconTypes iconType;
|
|
20
|
+
private String icon;
|
|
21
|
+
private int height;
|
|
22
|
+
private int width;
|
|
23
|
+
|
|
24
|
+
private ButtonNearDone(
|
|
25
|
+
AllIconTypes iconType,
|
|
26
|
+
String icon,
|
|
27
|
+
int height,
|
|
28
|
+
int width
|
|
29
|
+
) {
|
|
30
|
+
this.iconType = iconType;
|
|
31
|
+
this.icon = icon;
|
|
32
|
+
this.height = height;
|
|
33
|
+
this.width = width;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Nullable
|
|
37
|
+
public static ButtonNearDone generateFromPluginCall(
|
|
38
|
+
PluginCall call,
|
|
39
|
+
AssetManager assetManager
|
|
40
|
+
) throws IllegalArgumentException, RuntimeException {
|
|
41
|
+
JSObject buttonNearDone = call.getObject("buttonNearDone");
|
|
42
|
+
if (buttonNearDone == null) {
|
|
43
|
+
// Return null when "buttonNearDone" isn't configured, else throw an error
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
JSObject android = buttonNearDone.getJSObject("android");
|
|
48
|
+
if (android == null) {
|
|
49
|
+
throw new IllegalArgumentException("buttonNearDone.android is null");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
String iconType = android.getString("iconType", "asset");
|
|
53
|
+
if (!Objects.equals(iconType, "asset")) {
|
|
54
|
+
throw new IllegalArgumentException(
|
|
55
|
+
"buttonNearDone.android.iconType is not equal to \"asset\""
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
String icon = android.getString("icon");
|
|
60
|
+
if (icon == null) {
|
|
61
|
+
throw new IllegalArgumentException(
|
|
62
|
+
"buttonNearDone.android.icon is null"
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
InputStream fileInputString = null;
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
// Try to open the file
|
|
70
|
+
fileInputString = assetManager.open(icon);
|
|
71
|
+
// do nothing
|
|
72
|
+
} catch (IOException e) {
|
|
73
|
+
throw new IllegalArgumentException(
|
|
74
|
+
"buttonNearDone.android.icon cannot be found in the assetManager"
|
|
75
|
+
);
|
|
76
|
+
} finally {
|
|
77
|
+
// Close the input stream if it was opened
|
|
78
|
+
if (fileInputString != null) {
|
|
79
|
+
try {
|
|
80
|
+
fileInputString.close();
|
|
81
|
+
} catch (IOException e) {
|
|
82
|
+
throw new RuntimeException(e);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
Integer width = android.getInteger("width", 48);
|
|
87
|
+
|
|
88
|
+
Integer height = android.getInteger("height", 48);
|
|
89
|
+
return new ButtonNearDone(AllIconTypes.ASSET, icon, height, width);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public AllIconTypes getIconType() {
|
|
93
|
+
return iconType;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public String getIcon() {
|
|
97
|
+
return icon;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public int getHeight() {
|
|
101
|
+
return height;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public int getWidth() {
|
|
105
|
+
return width;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
8
109
|
private String title;
|
|
9
110
|
private boolean CloseModal;
|
|
10
111
|
private String CloseModalTitle;
|
|
11
112
|
private String CloseModalDescription;
|
|
12
113
|
private String CloseModalCancel;
|
|
114
|
+
private ButtonNearDone buttonNearDone;
|
|
13
115
|
private String CloseModalOk;
|
|
14
116
|
private String url;
|
|
15
117
|
private JSObject headers;
|
|
@@ -68,6 +170,14 @@ public class Options {
|
|
|
68
170
|
this.CloseModalDescription = CloseModalDescription;
|
|
69
171
|
}
|
|
70
172
|
|
|
173
|
+
public void setButtonNearDone(ButtonNearDone buttonNearDone) {
|
|
174
|
+
this.buttonNearDone = buttonNearDone;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public ButtonNearDone getButtonNearDone() {
|
|
178
|
+
return this.buttonNearDone;
|
|
179
|
+
}
|
|
180
|
+
|
|
71
181
|
public String getCloseModalCancel() {
|
|
72
182
|
return CloseModalCancel;
|
|
73
183
|
}
|
|
@@ -8,13 +8,18 @@ import android.content.ActivityNotFoundException;
|
|
|
8
8
|
import android.content.Context;
|
|
9
9
|
import android.content.DialogInterface;
|
|
10
10
|
import android.content.Intent;
|
|
11
|
+
import android.content.res.AssetManager;
|
|
11
12
|
import android.graphics.Bitmap;
|
|
12
13
|
import android.graphics.Color;
|
|
14
|
+
import android.graphics.Picture;
|
|
15
|
+
import android.graphics.drawable.PictureDrawable;
|
|
13
16
|
import android.net.Uri;
|
|
14
17
|
import android.net.http.SslError;
|
|
15
18
|
import android.text.TextUtils;
|
|
16
19
|
import android.util.Log;
|
|
20
|
+
import android.view.KeyEvent;
|
|
17
21
|
import android.view.View;
|
|
22
|
+
import android.view.ViewGroup.LayoutParams;
|
|
18
23
|
import android.view.Window;
|
|
19
24
|
import android.view.WindowManager;
|
|
20
25
|
import android.webkit.HttpAuthHandler;
|
|
@@ -31,7 +36,12 @@ import android.widget.ImageButton;
|
|
|
31
36
|
import android.widget.TextView;
|
|
32
37
|
import android.widget.Toast;
|
|
33
38
|
import android.widget.Toolbar;
|
|
39
|
+
import androidx.annotation.Nullable;
|
|
40
|
+
import com.caverock.androidsvg.SVG;
|
|
41
|
+
import com.caverock.androidsvg.SVGParseException;
|
|
34
42
|
import com.getcapacitor.JSObject;
|
|
43
|
+
import java.io.IOException;
|
|
44
|
+
import java.io.InputStream;
|
|
35
45
|
import java.net.URI;
|
|
36
46
|
import java.net.URISyntaxException;
|
|
37
47
|
import java.util.Arrays;
|
|
@@ -498,14 +508,65 @@ public class WebViewDialog extends Dialog {
|
|
|
498
508
|
if (TextUtils.equals(_options.getToolbarType(), "activity")) {
|
|
499
509
|
_toolbar.findViewById(R.id.forwardButton).setVisibility(View.GONE);
|
|
500
510
|
_toolbar.findViewById(R.id.backButton).setVisibility(View.GONE);
|
|
511
|
+
ImageButton buttonNearDoneView = _toolbar.findViewById(
|
|
512
|
+
R.id.buttonNearDone
|
|
513
|
+
);
|
|
514
|
+
buttonNearDoneView.setVisibility(View.GONE);
|
|
501
515
|
//TODO: Add share button functionality
|
|
502
516
|
} else if (TextUtils.equals(_options.getToolbarType(), "navigation")) {
|
|
517
|
+
ImageButton buttonNearDoneView = _toolbar.findViewById(
|
|
518
|
+
R.id.buttonNearDone
|
|
519
|
+
);
|
|
520
|
+
buttonNearDoneView.setVisibility(View.GONE);
|
|
503
521
|
//TODO: Remove share button when implemented
|
|
504
522
|
} else if (TextUtils.equals(_options.getToolbarType(), "blank")) {
|
|
505
523
|
_toolbar.setVisibility(View.GONE);
|
|
506
524
|
} else {
|
|
507
525
|
_toolbar.findViewById(R.id.forwardButton).setVisibility(View.GONE);
|
|
508
526
|
_toolbar.findViewById(R.id.backButton).setVisibility(View.GONE);
|
|
527
|
+
|
|
528
|
+
Options.ButtonNearDone buttonNearDone = _options.getButtonNearDone();
|
|
529
|
+
if (buttonNearDone != null) {
|
|
530
|
+
AssetManager assetManager = _context.getAssets();
|
|
531
|
+
|
|
532
|
+
// Open the SVG file from assets
|
|
533
|
+
InputStream inputStream = null;
|
|
534
|
+
try {
|
|
535
|
+
ImageButton buttonNearDoneView = _toolbar.findViewById(
|
|
536
|
+
R.id.buttonNearDone
|
|
537
|
+
);
|
|
538
|
+
buttonNearDoneView.setVisibility(View.VISIBLE);
|
|
539
|
+
|
|
540
|
+
inputStream = assetManager.open(buttonNearDone.getIcon());
|
|
541
|
+
|
|
542
|
+
SVG svg = SVG.getFromInputStream(inputStream);
|
|
543
|
+
Picture picture = svg.renderToPicture(
|
|
544
|
+
buttonNearDone.getWidth(),
|
|
545
|
+
buttonNearDone.getHeight()
|
|
546
|
+
);
|
|
547
|
+
PictureDrawable pictureDrawable = new PictureDrawable(picture);
|
|
548
|
+
|
|
549
|
+
buttonNearDoneView.setImageDrawable(pictureDrawable);
|
|
550
|
+
buttonNearDoneView.setOnClickListener(view ->
|
|
551
|
+
_options.getCallbacks().buttonNearDoneClicked()
|
|
552
|
+
);
|
|
553
|
+
} catch (IOException | SVGParseException e) {
|
|
554
|
+
throw new RuntimeException(e);
|
|
555
|
+
} finally {
|
|
556
|
+
if (inputStream != null) {
|
|
557
|
+
try {
|
|
558
|
+
inputStream.close();
|
|
559
|
+
} catch (IOException e) {
|
|
560
|
+
throw new RuntimeException(e);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
} else {
|
|
565
|
+
ImageButton buttonNearDoneView = _toolbar.findViewById(
|
|
566
|
+
R.id.buttonNearDone
|
|
567
|
+
);
|
|
568
|
+
buttonNearDoneView.setVisibility(View.GONE);
|
|
569
|
+
}
|
|
509
570
|
}
|
|
510
571
|
}
|
|
511
572
|
|
|
@@ -522,12 +583,20 @@ public class WebViewDialog extends Dialog {
|
|
|
522
583
|
|
|
523
584
|
if (!url.startsWith("https://") && !url.startsWith("http://")) {
|
|
524
585
|
try {
|
|
525
|
-
Intent intent
|
|
586
|
+
Intent intent;
|
|
587
|
+
if (url.startsWith("intent://")) {
|
|
588
|
+
intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
|
|
589
|
+
} else {
|
|
590
|
+
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
|
591
|
+
}
|
|
592
|
+
|
|
526
593
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
527
594
|
context.startActivity(intent);
|
|
528
595
|
return true;
|
|
529
596
|
} catch (ActivityNotFoundException e) {
|
|
530
597
|
// Do nothing
|
|
598
|
+
} catch (URISyntaxException e) {
|
|
599
|
+
// Do nothing
|
|
531
600
|
}
|
|
532
601
|
}
|
|
533
602
|
return false;
|
|
@@ -674,7 +743,14 @@ public class WebViewDialog extends Dialog {
|
|
|
674
743
|
_options.getPreShowScript() != null &&
|
|
675
744
|
!_options.getPreShowScript().isEmpty()
|
|
676
745
|
) {
|
|
677
|
-
|
|
746
|
+
executorService.execute(
|
|
747
|
+
new Runnable() {
|
|
748
|
+
@Override
|
|
749
|
+
public void run() {
|
|
750
|
+
injectPreShowScript();
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
);
|
|
678
754
|
}
|
|
679
755
|
|
|
680
756
|
ImageButton backButton = _toolbar.findViewById(R.id.backButton);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
|
2
2
|
<android.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
3
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
4
|
+
xmlns:tools="http://schemas.android.com/tools"
|
|
4
5
|
android:layout_width="match_parent"
|
|
5
6
|
android:layout_height="wrap_content"
|
|
6
7
|
android:background="#eeeeef"
|
|
@@ -15,6 +16,18 @@
|
|
|
15
16
|
android:layout_gravity="start"
|
|
16
17
|
android:background="#eeeeef"
|
|
17
18
|
android:contentDescription="@string/close_button" />
|
|
19
|
+
|
|
20
|
+
<ImageButton
|
|
21
|
+
android:id="@+id/buttonNearDone"
|
|
22
|
+
android:layout_width="wrap_content"
|
|
23
|
+
android:layout_height="wrap_content"
|
|
24
|
+
android:layout_gravity="start"
|
|
25
|
+
android:background="@android:color/transparent"
|
|
26
|
+
android:contentDescription="@string/button_near_done"
|
|
27
|
+
android:src="@drawable/ic_clear_24px"
|
|
28
|
+
android:translationX="64px"
|
|
29
|
+
tools:visibility="gone"
|
|
30
|
+
/>
|
|
18
31
|
<ImageButton
|
|
19
32
|
android:id="@+id/reloadButton"
|
|
20
33
|
android:layout_width="wrap_content"
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<string name="title_activity_browser">BrowserActivity</string>
|
|
4
4
|
<string name="title_activity_basic">BasicActivity</string>
|
|
5
5
|
<string name="close_button">Close Button</string>
|
|
6
|
+
<string name="button_near_done">Button near "done"</string>
|
|
6
7
|
<string name="reload_button">Reload Button</string>
|
|
7
8
|
<string name="back_button">Back Button</string>
|
|
8
9
|
<string name="title">Title</string>
|
package/dist/docs.json
CHANGED
|
@@ -221,6 +221,30 @@
|
|
|
221
221
|
],
|
|
222
222
|
"slug": "addlistenerurlchangeevent-"
|
|
223
223
|
},
|
|
224
|
+
{
|
|
225
|
+
"name": "addListener",
|
|
226
|
+
"signature": "(eventName: \"buttonNearDoneClick\", listenerFunc: ButtonNearListener) => Promise<PluginListenerHandle>",
|
|
227
|
+
"parameters": [
|
|
228
|
+
{
|
|
229
|
+
"name": "eventName",
|
|
230
|
+
"docs": "",
|
|
231
|
+
"type": "'buttonNearDoneClick'"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"name": "listenerFunc",
|
|
235
|
+
"docs": "",
|
|
236
|
+
"type": "ButtonNearListener"
|
|
237
|
+
}
|
|
238
|
+
],
|
|
239
|
+
"returns": "Promise<PluginListenerHandle>",
|
|
240
|
+
"tags": [],
|
|
241
|
+
"docs": "",
|
|
242
|
+
"complexTypes": [
|
|
243
|
+
"PluginListenerHandle",
|
|
244
|
+
"ButtonNearListener"
|
|
245
|
+
],
|
|
246
|
+
"slug": "addlistenerbuttonneardoneclick-"
|
|
247
|
+
},
|
|
224
248
|
{
|
|
225
249
|
"name": "addListener",
|
|
226
250
|
"signature": "(eventName: \"closeEvent\", listenerFunc: UrlChangeListener) => Promise<PluginListenerHandle>",
|
|
@@ -913,6 +937,20 @@
|
|
|
913
937
|
"String"
|
|
914
938
|
],
|
|
915
939
|
"type": "String"
|
|
940
|
+
},
|
|
941
|
+
{
|
|
942
|
+
"name": "buttonNearDone",
|
|
943
|
+
"tags": [
|
|
944
|
+
{
|
|
945
|
+
"text": "6.7.0",
|
|
946
|
+
"name": "since"
|
|
947
|
+
}
|
|
948
|
+
],
|
|
949
|
+
"docs": "buttonNearDone allows for a creation of a custom button. Please see [buttonNearDone.md](/buttonNearDone.md) for more info.",
|
|
950
|
+
"complexTypes": [
|
|
951
|
+
"String"
|
|
952
|
+
],
|
|
953
|
+
"type": "{ ios: { iconType: 'sf-symbol' | 'asset'; icon: String; }; android: { iconType: 'asset'; icon: String; width?: number | undefined; height?: number | undefined; }; } | undefined"
|
|
916
954
|
}
|
|
917
955
|
]
|
|
918
956
|
},
|
|
@@ -1784,6 +1822,17 @@
|
|
|
1784
1822
|
}
|
|
1785
1823
|
]
|
|
1786
1824
|
},
|
|
1825
|
+
{
|
|
1826
|
+
"name": "ButtonNearListener",
|
|
1827
|
+
"slug": "buttonnearlistener",
|
|
1828
|
+
"docs": "",
|
|
1829
|
+
"types": [
|
|
1830
|
+
{
|
|
1831
|
+
"text": "(state: {}): void",
|
|
1832
|
+
"complexTypes": []
|
|
1833
|
+
}
|
|
1834
|
+
]
|
|
1835
|
+
},
|
|
1787
1836
|
{
|
|
1788
1837
|
"name": "ConfirmBtnListener",
|
|
1789
1838
|
"slug": "confirmbtnlistener",
|
|
@@ -17,6 +17,7 @@ export interface BtnEvent {
|
|
|
17
17
|
}
|
|
18
18
|
export type UrlChangeListener = (state: UrlEvent) => void;
|
|
19
19
|
export type ConfirmBtnListener = (state: BtnEvent) => void;
|
|
20
|
+
export type ButtonNearListener = (state: {}) => void;
|
|
20
21
|
export declare enum BackgroundColor {
|
|
21
22
|
WHITE = "white",
|
|
22
23
|
BLACK = "black"
|
|
@@ -223,6 +224,23 @@ export interface OpenWebViewOptions {
|
|
|
223
224
|
* @since 6.6.0
|
|
224
225
|
*/
|
|
225
226
|
preShowScript?: String;
|
|
227
|
+
/**
|
|
228
|
+
* buttonNearDone allows for a creation of a custom button. Please see [buttonNearDone.md](/buttonNearDone.md) for more info.
|
|
229
|
+
*
|
|
230
|
+
* @since 6.7.0
|
|
231
|
+
*/
|
|
232
|
+
buttonNearDone?: {
|
|
233
|
+
ios: {
|
|
234
|
+
iconType: "sf-symbol" | "asset";
|
|
235
|
+
icon: String;
|
|
236
|
+
};
|
|
237
|
+
android: {
|
|
238
|
+
iconType: "asset";
|
|
239
|
+
icon: String;
|
|
240
|
+
width?: number;
|
|
241
|
+
height?: number;
|
|
242
|
+
};
|
|
243
|
+
};
|
|
226
244
|
}
|
|
227
245
|
export interface InAppBrowserPlugin {
|
|
228
246
|
/**
|
|
@@ -291,6 +309,7 @@ export interface InAppBrowserPlugin {
|
|
|
291
309
|
* @since 0.0.1
|
|
292
310
|
*/
|
|
293
311
|
addListener(eventName: "urlChangeEvent", listenerFunc: UrlChangeListener): Promise<PluginListenerHandle>;
|
|
312
|
+
addListener(eventName: "buttonNearDoneClick", listenerFunc: ButtonNearListener): Promise<PluginListenerHandle>;
|
|
294
313
|
/**
|
|
295
314
|
* Listen for close click only for openWebView
|
|
296
315
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAsBA,MAAM,CAAN,IAAY,eAGX;AAHD,WAAY,eAAe;IACzB,kCAAe,CAAA;IACf,kCAAe,CAAA;AACjB,CAAC,EAHW,eAAe,KAAf,eAAe,QAG1B;AACD,MAAM,CAAN,IAAY,WAKX;AALD,WAAY,WAAW;IACrB,oCAAqB,CAAA;IACrB,wCAAyB,CAAA;IACzB,8BAAe,CAAA;IACf,2BAAY,CAAA;AACd,CAAC,EALW,WAAW,KAAX,WAAW,QAKtB","sourcesContent":["import type { PluginListenerHandle } from \"@capacitor/core\";\n\nexport interface UrlEvent {\n /**\n * Emit when the url changes\n *\n * @since 0.0.1\n */\n url: string;\n}\nexport interface BtnEvent {\n /**\n * Emit when a button is clicked.\n *\n * @since 0.0.1\n */\n url: string;\n}\n\nexport type UrlChangeListener = (state: UrlEvent) => void;\nexport type ConfirmBtnListener = (state: BtnEvent) => void;\n\nexport enum BackgroundColor {\n WHITE = \"white\",\n BLACK = \"black\",\n}\nexport enum ToolBarType {\n ACTIVITY = \"activity\",\n NAVIGATION = \"navigation\",\n BLANK = \"blank\",\n DEFAULT = \"\",\n}\n\nexport interface Headers {\n [key: string]: string;\n}\n\nexport interface GetCookieOptions {\n url: string;\n includeHttpOnly?: boolean;\n}\n\nexport interface ClearCookieOptions {\n url: string;\n}\n\nexport interface Credentials {\n username: string;\n password: string;\n}\n\nexport interface OpenOptions {\n /**\n * Target URL to load.\n * @since 0.1.0\n */\n url: string;\n /**\n * Headers to send with the request.\n * @since 0.1.0\n */\n headers?: Headers;\n /**\n * Credentials to send with the request and all subsequent requests for the same host.\n * @since 6.1.0\n */\n credentials?: Credentials;\n /**\n * if true, the browser will be presented after the page is loaded, if false, the browser will be presented immediately.\n * @since 0.1.0\n */\n isPresentAfterPageLoad?: boolean;\n preventDeeplink?: boolean;\n}\n\nexport interface DisclaimerOptions {\n title: string;\n message: string;\n confirmBtn: string;\n cancelBtn: string;\n}\n\nexport interface OpenWebViewOptions {\n /**\n * Target URL to load.\n * @since 0.1.0\n */\n url: string;\n /**\n * Headers to send with the request.\n * @since 0.1.0\n */\n headers?: Headers;\n /**\n * Credentials to send with the request and all subsequent requests for the same host.\n * @since 6.1.0\n */\n credentials?: Credentials;\n /**\n * share options\n * @since 0.1.0\n */\n shareDisclaimer?: DisclaimerOptions;\n /**\n * Toolbar type\n * @since 0.1.0\n * @default ToolBarType.DEFAULT\n */\n toolbarType?: ToolBarType;\n /**\n * Share subject\n * @since 0.1.0\n */\n shareSubject?: string;\n /**\n * Title of the browser\n * @since 0.1.0\n * @default 'New Window'\n */\n title?: string;\n /**\n * Background color of the browser, only on IOS\n * @since 0.1.0\n * @default BackgroundColor.BLACK\n */\n backgroundColor?: BackgroundColor;\n /**\n * If true, active the native navigation within the webview, Android only\n *\n * @default false\n */\n activeNativeNavigationForWebview?: boolean;\n /**\n * Disable the possibility to go back on native application,\n * usefull to force user to stay on the webview, Android only\n *\n * @default false\n */\n disableGoBackOnNativeApplication?: boolean;\n /**\n * Open url in a new window fullscreen\n *\n * isPresentAfterPageLoad: if true, the browser will be presented after the page is loaded, if false, the browser will be presented immediately.\n * @since 0.1.0\n * @default false\n */\n isPresentAfterPageLoad?: boolean;\n /**\n * Whether the website in the webview is inspectable or not, ios only\n *\n * @default false\n */\n isInspectable?: boolean;\n /**\n * Whether the webview opening is animated or not, ios only\n *\n * @default true\n */\n isAnimated?: boolean;\n /**\n * Shows a reload button that reloads the web page\n * @since 1.0.15\n * @default false\n */\n showReloadButton?: boolean;\n /**\n * CloseModal: if true a confirm will be displayed when user clicks on close button, if false the browser will be closed immediately.\n *\n * @since 1.1.0\n * @default false\n */\n closeModal?: boolean;\n /**\n * CloseModalTitle: title of the confirm when user clicks on close button, only on IOS\n *\n * @since 1.1.0\n * @default 'Close'\n */\n closeModalTitle?: string;\n /**\n * CloseModalDescription: description of the confirm when user clicks on close button, only on IOS\n *\n * @since 1.1.0\n * @default 'Are you sure you want to close this window?'\n */\n closeModalDescription?: string;\n /**\n * CloseModalOk: text of the confirm button when user clicks on close button, only on IOS\n *\n * @since 1.1.0\n * @default 'Close'\n */\n closeModalOk?: string;\n /**\n * CloseModalCancel: text of the cancel button when user clicks on close button, only on IOS\n *\n * @since 1.1.0\n * @default 'Cancel'\n */\n closeModalCancel?: string;\n /**\n * visibleTitle: if true the website title would be shown else shown empty\n *\n * @since 1.2.5\n * @default true\n */\n visibleTitle?: boolean;\n /**\n * toolbarColor: color of the toolbar in hex format\n *\n * @since 1.2.5\n * @default '#ffffff''\n */\n toolbarColor?: string;\n /**\n * showArrow: if true an arrow would be shown instead of cross for closing the window\n *\n * @since 1.2.5\n * @default false\n */\n showArrow?: boolean;\n /**\n * ignoreUntrustedSSLError: if true, the webview will ignore untrusted SSL errors allowing the user to view the website.\n *\n * @since 6.1.0\n * @default false\n */\n ignoreUntrustedSSLError?: boolean;\n /**\n * preShowScript: if isPresentAfterPageLoad is true and this variable is set the plugin will inject a script before showing the browser.\n * This script will be run in an async context. The plugin will wait for the script to finish (max 10 seconds)\n *\n * @since 6.6.0\n */\n preShowScript?: String;\n}\n\nexport interface InAppBrowserPlugin {\n /**\n * Open url in a new window fullscreen\n *\n * @since 0.1.0\n */\n open(options: OpenOptions): Promise<any>;\n\n /**\n * Clear cookies of url\n *\n * @since 0.5.0\n */\n clearCookies(options: ClearCookieOptions): Promise<any>;\n /**\n * Clear all cookies\n *\n * @since 6.5.0\n */\n clearAllCookies(): Promise<any>;\n\n /**\n * Clear cache\n *\n * @since 6.5.0\n */\n clearCache(): Promise<any>;\n\n /**\n * Get cookies for a specific URL.\n * @param options The options, including the URL to get cookies for.\n * @returns A promise that resolves with the cookies.\n */\n getCookies(options: GetCookieOptions): Promise<Record<string, string>>;\n /**\n * Close the webview.\n */\n close(): Promise<any>;\n /**\n * Open url in a new webview with toolbars\n *\n * @since 0.1.0\n */\n openWebView(options: OpenWebViewOptions): Promise<any>;\n /**\n * Injects JavaScript code into the InAppBrowser window.\n */\n executeScript({ code }: { code: string }): Promise<void>;\n /**\n * Sends an event to the webview. you can listen to this event with addListener(\"messageFromWebview\", listenerFunc: (event: Record<string, any>) => void)\n * detail is the data you want to send to the webview, it's a requirement of Capacitor we cannot send direct objects\n * Your object has to be serializable to JSON, so no functions or other non-JSON-serializable types are allowed.\n */\n postMessage(options: { detail: Record<string, any> }): Promise<void>;\n /**\n * Sets the URL of the webview.\n */\n setUrl(options: { url: string }): Promise<any>;\n /**\n * Listen for url change, only for openWebView\n *\n * @since 0.0.1\n */\n addListener(\n eventName: \"urlChangeEvent\",\n listenerFunc: UrlChangeListener,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for close click only for openWebView\n *\n * @since 0.4.0\n */\n addListener(\n eventName: \"closeEvent\",\n listenerFunc: UrlChangeListener,\n ): Promise<PluginListenerHandle>;\n /**\n * Will be triggered when user clicks on confirm button when disclaimer is required, works only on iOS\n *\n * @since 0.0.1\n */\n addListener(\n eventName: \"confirmBtnClicked\",\n listenerFunc: ConfirmBtnListener,\n ): Promise<PluginListenerHandle>;\n /**\n * Will be triggered when event is sent from webview, to send an event to the webview use window.mobileApp.postMessage({ \"detail\": { \"message\": \"myMessage\" } })\n * detail is the data you want to send to the webview, it's a requirement of Capacitor we cannot send direct objects\n * Your object has to be serializable to JSON, so no functions or other non-JSON-serializable types are allowed.\n *\n * This method is inject at runtime in the webview\n */\n addListener(\n eventName: \"messageFromWebview\",\n listenerFunc: (event: { detail: Record<string, any> }) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Will be triggered when page is loaded\n */\n addListener(\n eventName: \"browserPageLoaded\",\n listenerFunc: () => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Will be triggered when page load error\n */\n addListener(\n eventName: \"pageLoadError\",\n listenerFunc: () => void,\n ): Promise<PluginListenerHandle>;\n /**\n * Remove all listeners for this plugin.\n *\n * @since 1.0.0\n */\n removeAllListeners(): Promise<void>;\n\n /**\n * Reload the current web page.\n *\n * @since 1.0.0\n */\n reload(): Promise<any>; // Add this line\n}\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAuBA,MAAM,CAAN,IAAY,eAGX;AAHD,WAAY,eAAe;IACzB,kCAAe,CAAA;IACf,kCAAe,CAAA;AACjB,CAAC,EAHW,eAAe,KAAf,eAAe,QAG1B;AACD,MAAM,CAAN,IAAY,WAKX;AALD,WAAY,WAAW;IACrB,oCAAqB,CAAA;IACrB,wCAAyB,CAAA;IACzB,8BAAe,CAAA;IACf,2BAAY,CAAA;AACd,CAAC,EALW,WAAW,KAAX,WAAW,QAKtB","sourcesContent":["import type { PluginListenerHandle } from \"@capacitor/core\";\n\nexport interface UrlEvent {\n /**\n * Emit when the url changes\n *\n * @since 0.0.1\n */\n url: string;\n}\nexport interface BtnEvent {\n /**\n * Emit when a button is clicked.\n *\n * @since 0.0.1\n */\n url: string;\n}\n\nexport type UrlChangeListener = (state: UrlEvent) => void;\nexport type ConfirmBtnListener = (state: BtnEvent) => void;\nexport type ButtonNearListener = (state: {}) => void;\n\nexport enum BackgroundColor {\n WHITE = \"white\",\n BLACK = \"black\",\n}\nexport enum ToolBarType {\n ACTIVITY = \"activity\",\n NAVIGATION = \"navigation\",\n BLANK = \"blank\",\n DEFAULT = \"\",\n}\n\nexport interface Headers {\n [key: string]: string;\n}\n\nexport interface GetCookieOptions {\n url: string;\n includeHttpOnly?: boolean;\n}\n\nexport interface ClearCookieOptions {\n url: string;\n}\n\nexport interface Credentials {\n username: string;\n password: string;\n}\n\nexport interface OpenOptions {\n /**\n * Target URL to load.\n * @since 0.1.0\n */\n url: string;\n /**\n * Headers to send with the request.\n * @since 0.1.0\n */\n headers?: Headers;\n /**\n * Credentials to send with the request and all subsequent requests for the same host.\n * @since 6.1.0\n */\n credentials?: Credentials;\n /**\n * if true, the browser will be presented after the page is loaded, if false, the browser will be presented immediately.\n * @since 0.1.0\n */\n isPresentAfterPageLoad?: boolean;\n preventDeeplink?: boolean;\n}\n\nexport interface DisclaimerOptions {\n title: string;\n message: string;\n confirmBtn: string;\n cancelBtn: string;\n}\n\nexport interface OpenWebViewOptions {\n /**\n * Target URL to load.\n * @since 0.1.0\n */\n url: string;\n /**\n * Headers to send with the request.\n * @since 0.1.0\n */\n headers?: Headers;\n /**\n * Credentials to send with the request and all subsequent requests for the same host.\n * @since 6.1.0\n */\n credentials?: Credentials;\n /**\n * share options\n * @since 0.1.0\n */\n shareDisclaimer?: DisclaimerOptions;\n /**\n * Toolbar type\n * @since 0.1.0\n * @default ToolBarType.DEFAULT\n */\n toolbarType?: ToolBarType;\n /**\n * Share subject\n * @since 0.1.0\n */\n shareSubject?: string;\n /**\n * Title of the browser\n * @since 0.1.0\n * @default 'New Window'\n */\n title?: string;\n /**\n * Background color of the browser, only on IOS\n * @since 0.1.0\n * @default BackgroundColor.BLACK\n */\n backgroundColor?: BackgroundColor;\n /**\n * If true, active the native navigation within the webview, Android only\n *\n * @default false\n */\n activeNativeNavigationForWebview?: boolean;\n /**\n * Disable the possibility to go back on native application,\n * usefull to force user to stay on the webview, Android only\n *\n * @default false\n */\n disableGoBackOnNativeApplication?: boolean;\n /**\n * Open url in a new window fullscreen\n *\n * isPresentAfterPageLoad: if true, the browser will be presented after the page is loaded, if false, the browser will be presented immediately.\n * @since 0.1.0\n * @default false\n */\n isPresentAfterPageLoad?: boolean;\n /**\n * Whether the website in the webview is inspectable or not, ios only\n *\n * @default false\n */\n isInspectable?: boolean;\n /**\n * Whether the webview opening is animated or not, ios only\n *\n * @default true\n */\n isAnimated?: boolean;\n /**\n * Shows a reload button that reloads the web page\n * @since 1.0.15\n * @default false\n */\n showReloadButton?: boolean;\n /**\n * CloseModal: if true a confirm will be displayed when user clicks on close button, if false the browser will be closed immediately.\n *\n * @since 1.1.0\n * @default false\n */\n closeModal?: boolean;\n /**\n * CloseModalTitle: title of the confirm when user clicks on close button, only on IOS\n *\n * @since 1.1.0\n * @default 'Close'\n */\n closeModalTitle?: string;\n /**\n * CloseModalDescription: description of the confirm when user clicks on close button, only on IOS\n *\n * @since 1.1.0\n * @default 'Are you sure you want to close this window?'\n */\n closeModalDescription?: string;\n /**\n * CloseModalOk: text of the confirm button when user clicks on close button, only on IOS\n *\n * @since 1.1.0\n * @default 'Close'\n */\n closeModalOk?: string;\n /**\n * CloseModalCancel: text of the cancel button when user clicks on close button, only on IOS\n *\n * @since 1.1.0\n * @default 'Cancel'\n */\n closeModalCancel?: string;\n /**\n * visibleTitle: if true the website title would be shown else shown empty\n *\n * @since 1.2.5\n * @default true\n */\n visibleTitle?: boolean;\n /**\n * toolbarColor: color of the toolbar in hex format\n *\n * @since 1.2.5\n * @default '#ffffff''\n */\n toolbarColor?: string;\n /**\n * showArrow: if true an arrow would be shown instead of cross for closing the window\n *\n * @since 1.2.5\n * @default false\n */\n showArrow?: boolean;\n /**\n * ignoreUntrustedSSLError: if true, the webview will ignore untrusted SSL errors allowing the user to view the website.\n *\n * @since 6.1.0\n * @default false\n */\n ignoreUntrustedSSLError?: boolean;\n /**\n * preShowScript: if isPresentAfterPageLoad is true and this variable is set the plugin will inject a script before showing the browser.\n * This script will be run in an async context. The plugin will wait for the script to finish (max 10 seconds)\n *\n * @since 6.6.0\n */\n preShowScript?: String;\n /**\n * buttonNearDone allows for a creation of a custom button. Please see [buttonNearDone.md](/buttonNearDone.md) for more info.\n *\n * @since 6.7.0\n */\n buttonNearDone?: {\n ios: {\n iconType: \"sf-symbol\" | \"asset\";\n icon: String;\n };\n android: {\n iconType: \"asset\";\n icon: String;\n width?: number;\n height?: number;\n };\n };\n}\n\nexport interface InAppBrowserPlugin {\n /**\n * Open url in a new window fullscreen\n *\n * @since 0.1.0\n */\n open(options: OpenOptions): Promise<any>;\n\n /**\n * Clear cookies of url\n *\n * @since 0.5.0\n */\n clearCookies(options: ClearCookieOptions): Promise<any>;\n /**\n * Clear all cookies\n *\n * @since 6.5.0\n */\n clearAllCookies(): Promise<any>;\n\n /**\n * Clear cache\n *\n * @since 6.5.0\n */\n clearCache(): Promise<any>;\n\n /**\n * Get cookies for a specific URL.\n * @param options The options, including the URL to get cookies for.\n * @returns A promise that resolves with the cookies.\n */\n getCookies(options: GetCookieOptions): Promise<Record<string, string>>;\n /**\n * Close the webview.\n */\n close(): Promise<any>;\n /**\n * Open url in a new webview with toolbars\n *\n * @since 0.1.0\n */\n openWebView(options: OpenWebViewOptions): Promise<any>;\n /**\n * Injects JavaScript code into the InAppBrowser window.\n */\n executeScript({ code }: { code: string }): Promise<void>;\n /**\n * Sends an event to the webview. you can listen to this event with addListener(\"messageFromWebview\", listenerFunc: (event: Record<string, any>) => void)\n * detail is the data you want to send to the webview, it's a requirement of Capacitor we cannot send direct objects\n * Your object has to be serializable to JSON, so no functions or other non-JSON-serializable types are allowed.\n */\n postMessage(options: { detail: Record<string, any> }): Promise<void>;\n /**\n * Sets the URL of the webview.\n */\n setUrl(options: { url: string }): Promise<any>;\n /**\n * Listen for url change, only for openWebView\n *\n * @since 0.0.1\n */\n addListener(\n eventName: \"urlChangeEvent\",\n listenerFunc: UrlChangeListener,\n ): Promise<PluginListenerHandle>;\n\n addListener(\n eventName: \"buttonNearDoneClick\",\n listenerFunc: ButtonNearListener,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for close click only for openWebView\n *\n * @since 0.4.0\n */\n addListener(\n eventName: \"closeEvent\",\n listenerFunc: UrlChangeListener,\n ): Promise<PluginListenerHandle>;\n /**\n * Will be triggered when user clicks on confirm button when disclaimer is required, works only on iOS\n *\n * @since 0.0.1\n */\n addListener(\n eventName: \"confirmBtnClicked\",\n listenerFunc: ConfirmBtnListener,\n ): Promise<PluginListenerHandle>;\n /**\n * Will be triggered when event is sent from webview, to send an event to the webview use window.mobileApp.postMessage({ \"detail\": { \"message\": \"myMessage\" } })\n * detail is the data you want to send to the webview, it's a requirement of Capacitor we cannot send direct objects\n * Your object has to be serializable to JSON, so no functions or other non-JSON-serializable types are allowed.\n *\n * This method is inject at runtime in the webview\n */\n addListener(\n eventName: \"messageFromWebview\",\n listenerFunc: (event: { detail: Record<string, any> }) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Will be triggered when page is loaded\n */\n addListener(\n eventName: \"browserPageLoaded\",\n listenerFunc: () => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Will be triggered when page load error\n */\n addListener(\n eventName: \"pageLoadError\",\n listenerFunc: () => void,\n ): Promise<PluginListenerHandle>;\n /**\n * Remove all listeners for this plugin.\n *\n * @since 1.0.0\n */\n removeAllListeners(): Promise<void>;\n\n /**\n * Reload the current web page.\n *\n * @since 1.0.0\n */\n reload(): Promise<any>; // Add this line\n}\n"]}
|
|
@@ -138,6 +138,39 @@ public class InAppBrowserPlugin: CAPPlugin {
|
|
|
138
138
|
return
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
var buttonNearDoneIcon: UIImage?
|
|
142
|
+
if let buttonNearDoneSettings = call.getObject("buttonNearDone") {
|
|
143
|
+
guard let iosSettingsRaw = buttonNearDoneSettings["ios"] else {
|
|
144
|
+
call.reject("IOS settings not found")
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
if !(iosSettingsRaw is JSObject) {
|
|
148
|
+
call.reject("IOS settings are not an object")
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
let iosSettings = iosSettingsRaw as! JSObject
|
|
152
|
+
|
|
153
|
+
guard let iconType = iosSettings["iconType"] as? String else {
|
|
154
|
+
call.reject("buttonNearDone.iconType is empty")
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
if iconType != "sf-symbol" && iconType != "asset" {
|
|
158
|
+
call.reject("IconType is neither 'sf-symbol' nor 'asset'")
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
guard let icon = iosSettings["icon"] as? String else {
|
|
162
|
+
call.reject("buttonNearDone.icon is empty")
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if iconType == "sf-symbol" {
|
|
167
|
+
buttonNearDoneIcon = UIImage(systemName: icon)
|
|
168
|
+
} else {
|
|
169
|
+
// UIImage(resource: ImageResource(name: "public/monkey.svg", bundle: Bundle.main))
|
|
170
|
+
buttonNearDoneIcon = UIImage(named: icon, in: Bundle.main, with: nil)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
141
174
|
let headers = call.getObject("headers", [:]).mapValues { String(describing: $0 as Any) }
|
|
142
175
|
let closeModal = call.getBool("closeModal", false)
|
|
143
176
|
let closeModalTitle = call.getString("closeModalTitle", "Close")
|
|
@@ -145,6 +178,7 @@ public class InAppBrowserPlugin: CAPPlugin {
|
|
|
145
178
|
let closeModalOk = call.getString("closeModalOk", "OK")
|
|
146
179
|
let closeModalCancel = call.getString("closeModalCancel", "Cancel")
|
|
147
180
|
let isInspectable = call.getBool("isInspectable", false)
|
|
181
|
+
let preventDeeplink = call.getBool("preventDeeplink", false)
|
|
148
182
|
let isAnimated = call.getBool("isAnimated", true)
|
|
149
183
|
|
|
150
184
|
var disclaimerContent = call.getObject("shareDisclaimer")
|
|
@@ -164,11 +198,12 @@ public class InAppBrowserPlugin: CAPPlugin {
|
|
|
164
198
|
let url = URL(string: urlString)
|
|
165
199
|
|
|
166
200
|
if self.isPresentAfterPageLoad {
|
|
167
|
-
self.webViewController = WKWebViewController.init(url: url!, headers: headers, isInspectable: isInspectable, credentials: credentials)
|
|
201
|
+
self.webViewController = WKWebViewController.init(url: url!, headers: headers, isInspectable: isInspectable, credentials: credentials, preventDeeplink: preventDeeplink)
|
|
168
202
|
} else {
|
|
169
203
|
self.webViewController = WKWebViewController.init()
|
|
170
204
|
self.webViewController?.setHeaders(headers: headers)
|
|
171
205
|
self.webViewController?.setCredentials(credentials: credentials)
|
|
206
|
+
self.webViewController?.setPreventDeeplink(preventDeeplink: preventDeeplink)
|
|
172
207
|
}
|
|
173
208
|
|
|
174
209
|
self.webViewController?.source = .remote(url!)
|
|
@@ -176,6 +211,9 @@ public class InAppBrowserPlugin: CAPPlugin {
|
|
|
176
211
|
self.webViewController?.leftNavigationBarItemTypes = self.getToolbarItems(toolbarType: toolbarType)
|
|
177
212
|
self.webViewController?.toolbarItemTypes = []
|
|
178
213
|
self.webViewController?.doneBarButtonItemPosition = .right
|
|
214
|
+
|
|
215
|
+
self.webViewController?.buttonNearDoneIcon = buttonNearDoneIcon
|
|
216
|
+
|
|
179
217
|
if call.getBool("showArrow", false) {
|
|
180
218
|
self.webViewController?.stopBarButtonItemImage = UIImage(named: "Forward@3x", in: Bundle(for: InAppBrowserPlugin.self), compatibleWith: nil)
|
|
181
219
|
}
|
|
@@ -290,6 +328,7 @@ public class InAppBrowserPlugin: CAPPlugin {
|
|
|
290
328
|
}
|
|
291
329
|
|
|
292
330
|
let isInspectable = call.getBool("isInspectable", false)
|
|
331
|
+
let preventDeeplink = call.getBool("preventDeeplink", false)
|
|
293
332
|
|
|
294
333
|
self.currentPluginCall = call
|
|
295
334
|
|
|
@@ -313,11 +352,12 @@ public class InAppBrowserPlugin: CAPPlugin {
|
|
|
313
352
|
let url = URL(string: urlString)
|
|
314
353
|
|
|
315
354
|
if self.isPresentAfterPageLoad {
|
|
316
|
-
self.webViewController = WKWebViewController.init(url: url!, headers: headers, isInspectable: isInspectable, credentials: credentials)
|
|
355
|
+
self.webViewController = WKWebViewController.init(url: url!, headers: headers, isInspectable: isInspectable, credentials: credentials, preventDeeplink: preventDeeplink)
|
|
317
356
|
} else {
|
|
318
357
|
self.webViewController = WKWebViewController.init()
|
|
319
358
|
self.webViewController?.setHeaders(headers: headers)
|
|
320
359
|
self.webViewController?.setCredentials(credentials: credentials)
|
|
360
|
+
self.webViewController?.setPreventDeeplink(preventDeeplink: preventDeeplink)
|
|
321
361
|
}
|
|
322
362
|
|
|
323
363
|
self.webViewController?.source = .remote(url!)
|
|
@@ -67,11 +67,12 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
67
67
|
self.initWebview()
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
public init(url: URL, headers: [String: String], isInspectable: Bool, credentials: WKWebViewCredentials? = nil) {
|
|
70
|
+
public init(url: URL, headers: [String: String], isInspectable: Bool, credentials: WKWebViewCredentials? = nil, preventDeeplink: Bool) {
|
|
71
71
|
super.init(nibName: nil, bundle: nil)
|
|
72
72
|
self.source = .remote(url)
|
|
73
73
|
self.credentials = credentials
|
|
74
74
|
self.setHeaders(headers: headers)
|
|
75
|
+
self.setPreventDeeplink(preventDeeplink: preventDeeplink)
|
|
75
76
|
self.initWebview(isInspectable: isInspectable)
|
|
76
77
|
}
|
|
77
78
|
|
|
@@ -99,6 +100,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
99
100
|
open var closeModalCancel = ""
|
|
100
101
|
open var ignoreUntrustedSSLError = false
|
|
101
102
|
var viewWasPresented = false
|
|
103
|
+
var preventDeeplink: Bool = false
|
|
102
104
|
|
|
103
105
|
internal var preShowSemaphore: DispatchSemaphore?
|
|
104
106
|
internal var preShowError: String?
|
|
@@ -115,6 +117,10 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
115
117
|
}
|
|
116
118
|
}
|
|
117
119
|
|
|
120
|
+
func setPreventDeeplink(preventDeeplink: Bool) {
|
|
121
|
+
self.preventDeeplink = preventDeeplink
|
|
122
|
+
}
|
|
123
|
+
|
|
118
124
|
internal var customUserAgent: String? {
|
|
119
125
|
didSet {
|
|
120
126
|
guard let agent = userAgent else {
|
|
@@ -155,6 +161,8 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
155
161
|
open var stopBarButtonItemImage: UIImage?
|
|
156
162
|
open var activityBarButtonItemImage: UIImage?
|
|
157
163
|
|
|
164
|
+
open var buttonNearDoneIcon: UIImage?
|
|
165
|
+
|
|
158
166
|
fileprivate var webView: WKWebView?
|
|
159
167
|
fileprivate var progressView: UIProgressView?
|
|
160
168
|
|
|
@@ -274,7 +282,9 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
274
282
|
};
|
|
275
283
|
}
|
|
276
284
|
"""
|
|
277
|
-
|
|
285
|
+
DispatchQueue.main.async {
|
|
286
|
+
self.webView?.evaluateJavaScript(script, completionHandler: nil)
|
|
287
|
+
}
|
|
278
288
|
}
|
|
279
289
|
|
|
280
290
|
open func initWebview(isInspectable: Bool = true) {
|
|
@@ -398,25 +408,28 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
398
408
|
override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
|
|
399
409
|
switch keyPath {
|
|
400
410
|
case estimatedProgressKeyPath?:
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
411
|
+
DispatchQueue.main.async {
|
|
412
|
+
guard let estimatedProgress = self.webView?.estimatedProgress else {
|
|
413
|
+
return
|
|
414
|
+
}
|
|
415
|
+
self.progressView?.alpha = 1
|
|
416
|
+
self.progressView?.setProgress(Float(estimatedProgress), animated: true)
|
|
417
|
+
|
|
418
|
+
if estimatedProgress >= 1.0 {
|
|
419
|
+
UIView.animate(withDuration: 0.3, delay: 0.3, options: .curveEaseOut, animations: {
|
|
420
|
+
self.progressView?.alpha = 0
|
|
421
|
+
}, completion: {
|
|
422
|
+
_ in
|
|
423
|
+
self.progressView?.setProgress(0, animated: false)
|
|
424
|
+
})
|
|
425
|
+
}
|
|
414
426
|
}
|
|
415
427
|
case titleKeyPath?:
|
|
416
428
|
if self.hasDynamicTitle {
|
|
417
429
|
self.navigationItem.title = webView?.url?.host
|
|
418
430
|
}
|
|
419
431
|
case "URL":
|
|
432
|
+
|
|
420
433
|
self.capBrowserPlugin?.notifyListeners("urlChangeEvent", data: ["url": webView?.url?.absoluteString ?? ""])
|
|
421
434
|
self.injectJavaScriptInterface()
|
|
422
435
|
default:
|
|
@@ -440,7 +453,9 @@ public extension WKWebViewController {
|
|
|
440
453
|
}
|
|
441
454
|
|
|
442
455
|
func load(remote: URL) {
|
|
443
|
-
|
|
456
|
+
DispatchQueue.main.async {
|
|
457
|
+
self.webView?.load(self.createRequest(url: remote))
|
|
458
|
+
}
|
|
444
459
|
}
|
|
445
460
|
|
|
446
461
|
func load(file: URL, access: URL) {
|
|
@@ -583,13 +598,17 @@ fileprivate extension WKWebViewController {
|
|
|
583
598
|
return UIBarButtonItem()
|
|
584
599
|
}
|
|
585
600
|
|
|
586
|
-
|
|
601
|
+
var rightBarButtons = rightNavigaionBarItemTypes.map {
|
|
587
602
|
barButtonItemType in
|
|
588
603
|
if let barButtonItem = barButtonItem(barButtonItemType) {
|
|
589
604
|
return barButtonItem
|
|
590
605
|
}
|
|
591
606
|
return UIBarButtonItem()
|
|
592
607
|
}
|
|
608
|
+
if rightBarButtons.count == 1 && buttonNearDoneIcon != nil && rightBarButtons[0] == doneBarButtonItem {
|
|
609
|
+
rightBarButtons.append(UIBarButtonItem(image: buttonNearDoneIcon, style: .plain, target: self, action: #selector(buttonNearDoneDidClick)))
|
|
610
|
+
}
|
|
611
|
+
navigationItem.rightBarButtonItems = rightBarButtons
|
|
593
612
|
|
|
594
613
|
if toolbarItemTypes.count > 0 {
|
|
595
614
|
for index in 0..<toolbarItemTypes.count - 1 {
|
|
@@ -597,13 +616,14 @@ fileprivate extension WKWebViewController {
|
|
|
597
616
|
}
|
|
598
617
|
}
|
|
599
618
|
|
|
600
|
-
|
|
619
|
+
let gen = toolbarItemTypes.map {
|
|
601
620
|
barButtonItemType -> UIBarButtonItem in
|
|
602
621
|
if let barButtonItem = barButtonItem(barButtonItemType) {
|
|
603
622
|
return barButtonItem
|
|
604
623
|
}
|
|
605
624
|
return UIBarButtonItem()
|
|
606
|
-
}
|
|
625
|
+
}
|
|
626
|
+
setToolbarItems(gen, animated: true)
|
|
607
627
|
}
|
|
608
628
|
|
|
609
629
|
func updateBarButtonItems() {
|
|
@@ -722,6 +742,10 @@ fileprivate extension WKWebViewController {
|
|
|
722
742
|
webView?.goForward()
|
|
723
743
|
}
|
|
724
744
|
|
|
745
|
+
@objc func buttonNearDoneDidClick(sender: AnyObject) {
|
|
746
|
+
self.capBrowserPlugin?.notifyListeners("buttonNearDoneClick", data: [:])
|
|
747
|
+
}
|
|
748
|
+
|
|
725
749
|
@objc func reloadDidClick(sender: AnyObject) {
|
|
726
750
|
webView?.stopLoading()
|
|
727
751
|
if webView?.url != nil {
|
|
@@ -771,6 +795,7 @@ fileprivate extension WKWebViewController {
|
|
|
771
795
|
self.present(alert, animated: true, completion: nil)
|
|
772
796
|
} else {
|
|
773
797
|
let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil)
|
|
798
|
+
#imageLiteral(resourceName: "simulator_screenshot_B8B44B8D-EB30-425C-9BF4-1F37697A8459.png")
|
|
774
799
|
activityViewController.setValue(self.shareSubject ?? self.title, forKey: "subject")
|
|
775
800
|
activityViewController.popoverPresentationController?.barButtonItem = (sender as! UIBarButtonItem)
|
|
776
801
|
self.present(activityViewController, animated: true, completion: nil)
|
|
@@ -946,6 +971,10 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
946
971
|
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
|
|
947
972
|
var actionPolicy: WKNavigationActionPolicy = .allow
|
|
948
973
|
|
|
974
|
+
if self.preventDeeplink {
|
|
975
|
+
actionPolicy = .preventDeeplinkActionPolicy
|
|
976
|
+
}
|
|
977
|
+
|
|
949
978
|
defer {
|
|
950
979
|
decisionHandler(actionPolicy)
|
|
951
980
|
}
|
|
@@ -981,3 +1010,7 @@ class BlockBarButtonItem: UIBarButtonItem {
|
|
|
981
1010
|
|
|
982
1011
|
var block: ((WKWebViewController) -> Void)?
|
|
983
1012
|
}
|
|
1013
|
+
|
|
1014
|
+
extension WKNavigationActionPolicy {
|
|
1015
|
+
static let preventDeeplinkActionPolicy = WKNavigationActionPolicy(rawValue: WKNavigationActionPolicy.allow.rawValue + 2)!
|
|
1016
|
+
}
|