@capgo/inappbrowser 7.6.4 → 7.6.7
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 +22 -19
- package/android/src/main/AndroidManifest.xml +12 -1
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/InAppBrowserPlugin.java +113 -78
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +527 -38
- package/android/src/main/res/xml/file_paths.xml +14 -0
- package/dist/docs.json +32 -60
- package/dist/esm/definitions.d.ts +1 -11
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Plugin/InAppBrowserPlugin.swift +38 -22
- package/ios/Plugin/WKWebViewController.swift +4 -107
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,6 +24,11 @@ InAppBrowser.open({ url: "YOUR_URL" });
|
|
|
24
24
|
|
|
25
25
|
Web platform is not supported. Use `window.open` instead.
|
|
26
26
|
|
|
27
|
+
|
|
28
|
+
### Test app and code:
|
|
29
|
+
|
|
30
|
+
https://github.com/Cap-go/demo-app/blob/main/src/views/plugins/Web.vue
|
|
31
|
+
|
|
27
32
|
### Camera usage
|
|
28
33
|
|
|
29
34
|
#### Android
|
|
@@ -147,7 +152,7 @@ window.mobileApp.close();
|
|
|
147
152
|
open(options: OpenOptions) => Promise<any>
|
|
148
153
|
```
|
|
149
154
|
|
|
150
|
-
Open url in a new window fullscreen
|
|
155
|
+
Open url in a new window fullscreen, on android it use chrome custom tabs, on ios it use SFSafariViewController
|
|
151
156
|
|
|
152
157
|
| Param | Type |
|
|
153
158
|
| ------------- | --------------------------------------------------- |
|
|
@@ -479,24 +484,11 @@ Reload the current web page.
|
|
|
479
484
|
|
|
480
485
|
#### OpenOptions
|
|
481
486
|
|
|
482
|
-
| Prop | Type
|
|
483
|
-
| ---------------------------- |
|
|
484
|
-
| **`url`** | <code>string</code>
|
|
485
|
-
| **`
|
|
486
|
-
| **`
|
|
487
|
-
| **`isPresentAfterPageLoad`** | <code>boolean</code> | if true, the browser will be presented after the page is loaded, if false, the browser will be presented immediately. | 0.1.0 |
|
|
488
|
-
| **`preventDeeplink`** | <code>boolean</code> | if true the deeplink will not be opened, if false the deeplink will be opened when clicked on the link | 0.1.0 |
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
#### Headers
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
#### Credentials
|
|
495
|
-
|
|
496
|
-
| Prop | Type |
|
|
497
|
-
| -------------- | ------------------- |
|
|
498
|
-
| **`username`** | <code>string</code> |
|
|
499
|
-
| **`password`** | <code>string</code> |
|
|
487
|
+
| Prop | Type | Description | Since |
|
|
488
|
+
| ---------------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------- | ----- |
|
|
489
|
+
| **`url`** | <code>string</code> | Target URL to load. | 0.1.0 |
|
|
490
|
+
| **`isPresentAfterPageLoad`** | <code>boolean</code> | if true, the browser will be presented after the page is loaded, if false, the browser will be presented immediately. | 0.1.0 |
|
|
491
|
+
| **`preventDeeplink`** | <code>boolean</code> | if true the deeplink will not be opened, if false the deeplink will be opened when clicked on the link | 0.1.0 |
|
|
500
492
|
|
|
501
493
|
|
|
502
494
|
#### ClearCookieOptions
|
|
@@ -559,6 +551,17 @@ Reload the current web page.
|
|
|
559
551
|
| **`textZoom`** | <code>number</code> | textZoom: sets the text zoom of the page in percent. Allows users to increase or decrease the text size for better readability. | <code>100</code> | 7.6.0 |
|
|
560
552
|
|
|
561
553
|
|
|
554
|
+
#### Headers
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
#### Credentials
|
|
558
|
+
|
|
559
|
+
| Prop | Type |
|
|
560
|
+
| -------------- | ------------------- |
|
|
561
|
+
| **`username`** | <code>string</code> |
|
|
562
|
+
| **`password`** | <code>string</code> |
|
|
563
|
+
|
|
564
|
+
|
|
562
565
|
#### DisclaimerOptions
|
|
563
566
|
|
|
564
567
|
| Prop | Type | Description | Default |
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
2
|
<queries>
|
|
4
3
|
<intent>
|
|
@@ -8,4 +7,16 @@
|
|
|
8
7
|
</intent>
|
|
9
8
|
</queries>
|
|
10
9
|
<uses-permission android:name="android.permission.CAMERA"/>
|
|
10
|
+
|
|
11
|
+
<application>
|
|
12
|
+
<provider
|
|
13
|
+
android:name="androidx.core.content.FileProvider"
|
|
14
|
+
android:authorities="${applicationId}.fileprovider"
|
|
15
|
+
android:exported="false"
|
|
16
|
+
android:grantUriPermissions="true">
|
|
17
|
+
<meta-data
|
|
18
|
+
android:name="android.support.FILE_PROVIDER_PATHS"
|
|
19
|
+
android:resource="@xml/file_paths" />
|
|
20
|
+
</provider>
|
|
21
|
+
</application>
|
|
11
22
|
</manifest>
|
|
@@ -12,6 +12,9 @@ import android.text.TextUtils;
|
|
|
12
12
|
import android.util.Log;
|
|
13
13
|
import android.webkit.CookieManager;
|
|
14
14
|
import android.webkit.PermissionRequest;
|
|
15
|
+
import androidx.activity.result.ActivityResult;
|
|
16
|
+
import androidx.activity.result.ActivityResultLauncher;
|
|
17
|
+
import androidx.activity.result.contract.ActivityResultContracts;
|
|
15
18
|
import androidx.annotation.NonNull;
|
|
16
19
|
import androidx.browser.customtabs.CustomTabsCallback;
|
|
17
20
|
import androidx.browser.customtabs.CustomTabsClient;
|
|
@@ -29,7 +32,6 @@ import com.getcapacitor.annotation.PermissionCallback;
|
|
|
29
32
|
import java.lang.reflect.Field;
|
|
30
33
|
import java.util.ArrayList;
|
|
31
34
|
import java.util.Iterator;
|
|
32
|
-
import java.util.Objects;
|
|
33
35
|
import java.util.regex.Pattern;
|
|
34
36
|
import java.util.regex.PatternSyntaxException;
|
|
35
37
|
import org.json.JSONException;
|
|
@@ -62,6 +64,54 @@ public class InAppBrowserPlugin
|
|
|
62
64
|
|
|
63
65
|
private PermissionRequest currentPermissionRequest;
|
|
64
66
|
|
|
67
|
+
private ActivityResultLauncher<Intent> fileChooserLauncher;
|
|
68
|
+
|
|
69
|
+
@Override
|
|
70
|
+
public void load() {
|
|
71
|
+
super.load();
|
|
72
|
+
fileChooserLauncher = getActivity()
|
|
73
|
+
.registerForActivityResult(
|
|
74
|
+
new ActivityResultContracts.StartActivityForResult(),
|
|
75
|
+
this::handleFileChooserResult
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private void handleFileChooserResult(ActivityResult result) {
|
|
80
|
+
if (webViewDialog != null && webViewDialog.mFilePathCallback != null) {
|
|
81
|
+
Uri[] results = null;
|
|
82
|
+
Intent data = result.getData();
|
|
83
|
+
|
|
84
|
+
if (result.getResultCode() == Activity.RESULT_OK) {
|
|
85
|
+
// Handle camera capture result
|
|
86
|
+
if (
|
|
87
|
+
webViewDialog.tempCameraUri != null &&
|
|
88
|
+
(data == null || data.getData() == null)
|
|
89
|
+
) {
|
|
90
|
+
results = new Uri[] { webViewDialog.tempCameraUri };
|
|
91
|
+
}
|
|
92
|
+
// Handle regular file picker result
|
|
93
|
+
else if (data != null) {
|
|
94
|
+
if (data.getClipData() != null) {
|
|
95
|
+
// Handle multiple files
|
|
96
|
+
int count = data.getClipData().getItemCount();
|
|
97
|
+
results = new Uri[count];
|
|
98
|
+
for (int i = 0; i < count; i++) {
|
|
99
|
+
results[i] = data.getClipData().getItemAt(i).getUri();
|
|
100
|
+
}
|
|
101
|
+
} else if (data.getData() != null) {
|
|
102
|
+
// Handle single file
|
|
103
|
+
results = new Uri[] { data.getData() };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Send the result to WebView and clean up
|
|
109
|
+
webViewDialog.mFilePathCallback.onReceiveValue(results);
|
|
110
|
+
webViewDialog.mFilePathCallback = null;
|
|
111
|
+
webViewDialog.tempCameraUri = null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
65
115
|
public void handleMicrophonePermissionRequest(PermissionRequest request) {
|
|
66
116
|
this.currentPermissionRequest = request;
|
|
67
117
|
if (getPermissionState("microphone") != PermissionState.GRANTED) {
|
|
@@ -126,57 +176,6 @@ public class InAppBrowserPlugin
|
|
|
126
176
|
}
|
|
127
177
|
}
|
|
128
178
|
|
|
129
|
-
@Override
|
|
130
|
-
public void handleOnActivityResult(
|
|
131
|
-
int requestCode,
|
|
132
|
-
int resultCode,
|
|
133
|
-
Intent data
|
|
134
|
-
) {
|
|
135
|
-
super.handleOnActivityResult(requestCode, resultCode, data);
|
|
136
|
-
|
|
137
|
-
// Handle file chooser result
|
|
138
|
-
if (requestCode == WebViewDialog.FILE_CHOOSER_REQUEST_CODE) {
|
|
139
|
-
if (webViewDialog != null && webViewDialog.mFilePathCallback != null) {
|
|
140
|
-
Uri[] results = null;
|
|
141
|
-
|
|
142
|
-
// Check if response is valid
|
|
143
|
-
if (resultCode == Activity.RESULT_OK) {
|
|
144
|
-
if (data != null) {
|
|
145
|
-
// Get the data
|
|
146
|
-
if (data.getClipData() != null) {
|
|
147
|
-
// Handle multiple files
|
|
148
|
-
int count = data.getClipData().getItemCount();
|
|
149
|
-
results = new Uri[count];
|
|
150
|
-
for (int i = 0; i < count; i++) {
|
|
151
|
-
results[i] = data.getClipData().getItemAt(i).getUri();
|
|
152
|
-
}
|
|
153
|
-
} else if (data.getData() != null) {
|
|
154
|
-
// Handle single file
|
|
155
|
-
results = new Uri[] { data.getData() };
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Send the result to WebView
|
|
161
|
-
webViewDialog.mFilePathCallback.onReceiveValue(results);
|
|
162
|
-
webViewDialog.mFilePathCallback = null;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
@PermissionCallback
|
|
168
|
-
private void cameraPermissionCallback() {
|
|
169
|
-
if (getPermissionState("camera") == PermissionState.GRANTED) {
|
|
170
|
-
grantCameraPermission();
|
|
171
|
-
} else {
|
|
172
|
-
if (currentPermissionRequest != null) {
|
|
173
|
-
currentPermissionRequest.deny();
|
|
174
|
-
currentPermissionRequest = null;
|
|
175
|
-
}
|
|
176
|
-
// Handle the case where permission was not granted
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
179
|
@PermissionCallback
|
|
181
180
|
private void cameraPermissionCallback(PluginCall call) {
|
|
182
181
|
if (getPermissionState("camera") == PermissionState.GRANTED) {
|
|
@@ -194,7 +193,23 @@ public class InAppBrowserPlugin
|
|
|
194
193
|
currentPermissionRequest.deny();
|
|
195
194
|
currentPermissionRequest = null;
|
|
196
195
|
}
|
|
197
|
-
|
|
196
|
+
|
|
197
|
+
// Reject only if there's a call - could be null for WebViewDialog flow
|
|
198
|
+
if (call != null) {
|
|
199
|
+
call.reject("Camera permission is required");
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@PermissionCallback
|
|
205
|
+
private void cameraPermissionCallback() {
|
|
206
|
+
if (getPermissionState("camera") == PermissionState.GRANTED) {
|
|
207
|
+
grantCameraPermission();
|
|
208
|
+
} else {
|
|
209
|
+
if (currentPermissionRequest != null) {
|
|
210
|
+
currentPermissionRequest.deny();
|
|
211
|
+
currentPermissionRequest = null;
|
|
212
|
+
}
|
|
198
213
|
}
|
|
199
214
|
}
|
|
200
215
|
|
|
@@ -210,15 +225,16 @@ public class InAppBrowserPlugin
|
|
|
210
225
|
CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
|
|
211
226
|
@Override
|
|
212
227
|
public void onCustomTabsServiceConnected(
|
|
213
|
-
|
|
228
|
+
ComponentName name,
|
|
214
229
|
CustomTabsClient client
|
|
215
230
|
) {
|
|
216
231
|
customTabsClient = client;
|
|
217
|
-
client.warmup(0);
|
|
218
232
|
}
|
|
219
233
|
|
|
220
234
|
@Override
|
|
221
|
-
public void onServiceDisconnected(ComponentName name) {
|
|
235
|
+
public void onServiceDisconnected(ComponentName name) {
|
|
236
|
+
customTabsClient = null;
|
|
237
|
+
}
|
|
222
238
|
};
|
|
223
239
|
|
|
224
240
|
@PluginMethod
|
|
@@ -252,9 +268,17 @@ public class InAppBrowserPlugin
|
|
|
252
268
|
@PluginMethod
|
|
253
269
|
public void open(PluginCall call) {
|
|
254
270
|
String url = call.getString("url");
|
|
271
|
+
if (url == null) {
|
|
272
|
+
call.reject("URL is required");
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
255
275
|
|
|
256
276
|
// get the deeplink prevention, if provided
|
|
257
277
|
Boolean preventDeeplink = call.getBoolean("preventDeeplink", null);
|
|
278
|
+
Boolean isPresentAfterPageLoad = call.getBoolean(
|
|
279
|
+
"isPresentAfterPageLoad",
|
|
280
|
+
false
|
|
281
|
+
);
|
|
258
282
|
|
|
259
283
|
if (url == null || TextUtils.isEmpty(url)) {
|
|
260
284
|
call.reject("Invalid URL");
|
|
@@ -294,6 +318,10 @@ public class InAppBrowserPlugin
|
|
|
294
318
|
}
|
|
295
319
|
}
|
|
296
320
|
|
|
321
|
+
if (isPresentAfterPageLoad) {
|
|
322
|
+
tabsIntent.intent.putExtra("isPresentAfterPageLoad", true);
|
|
323
|
+
}
|
|
324
|
+
|
|
297
325
|
tabsIntent.launchUrl(getContext(), Uri.parse(url));
|
|
298
326
|
|
|
299
327
|
call.resolve();
|
|
@@ -473,21 +501,7 @@ public class InAppBrowserPlugin
|
|
|
473
501
|
Log.e("InAppBrowser", "Vector resource not found: " + icon);
|
|
474
502
|
// List available drawable resources to help debugging
|
|
475
503
|
try {
|
|
476
|
-
|
|
477
|
-
StringBuilder availableResources = new StringBuilder(
|
|
478
|
-
"Available resources: "
|
|
479
|
-
);
|
|
480
|
-
for (int i = 0; i < Math.min(10, drawables.length); i++) {
|
|
481
|
-
availableResources
|
|
482
|
-
.append(drawables[i].getName())
|
|
483
|
-
.append(", ");
|
|
484
|
-
}
|
|
485
|
-
if (drawables.length > 10) {
|
|
486
|
-
availableResources
|
|
487
|
-
.append("... (")
|
|
488
|
-
.append(drawables.length - 10)
|
|
489
|
-
.append(" more)");
|
|
490
|
-
}
|
|
504
|
+
final StringBuilder availableResources = getStringBuilder();
|
|
491
505
|
Log.d("InAppBrowser", availableResources.toString());
|
|
492
506
|
} catch (Exception e) {
|
|
493
507
|
Log.e(
|
|
@@ -534,7 +548,7 @@ public class InAppBrowserPlugin
|
|
|
534
548
|
|
|
535
549
|
// Validate preShowScript requires isPresentAfterPageLoad
|
|
536
550
|
if (
|
|
537
|
-
call.
|
|
551
|
+
call.getData().has("preShowScript") &&
|
|
538
552
|
!Boolean.TRUE.equals(call.getBoolean("isPresentAfterPageLoad", false))
|
|
539
553
|
) {
|
|
540
554
|
call.reject("preShowScript requires isPresentAfterPageLoad to be true");
|
|
@@ -553,10 +567,10 @@ public class InAppBrowserPlugin
|
|
|
553
567
|
} else {
|
|
554
568
|
// Reject if closeModal is false but closeModal options are provided
|
|
555
569
|
if (
|
|
556
|
-
call.
|
|
557
|
-
call.
|
|
558
|
-
call.
|
|
559
|
-
call.
|
|
570
|
+
call.getData().has("closeModalTitle") ||
|
|
571
|
+
call.getData().has("closeModalDescription") ||
|
|
572
|
+
call.getData().has("closeModalOk") ||
|
|
573
|
+
call.getData().has("closeModalCancel")
|
|
560
574
|
) {
|
|
561
575
|
call.reject("closeModal options require closeModal to be true");
|
|
562
576
|
return;
|
|
@@ -565,13 +579,16 @@ public class InAppBrowserPlugin
|
|
|
565
579
|
}
|
|
566
580
|
|
|
567
581
|
// Validate shareDisclaimer requires shareSubject
|
|
568
|
-
if (
|
|
582
|
+
if (
|
|
583
|
+
call.getData().has("shareDisclaimer") &&
|
|
584
|
+
!call.getData().has("shareSubject")
|
|
585
|
+
) {
|
|
569
586
|
call.reject("shareDisclaimer requires shareSubject to be provided");
|
|
570
587
|
return;
|
|
571
588
|
}
|
|
572
589
|
|
|
573
590
|
// Validate buttonNearDone compatibility with toolbar type
|
|
574
|
-
if (call.
|
|
591
|
+
if (call.getData().has("buttonNearDone")) {
|
|
575
592
|
String toolbarType = options.getToolbarType();
|
|
576
593
|
if (
|
|
577
594
|
TextUtils.equals(toolbarType, "activity") ||
|
|
@@ -695,6 +712,24 @@ public class InAppBrowserPlugin
|
|
|
695
712
|
);
|
|
696
713
|
}
|
|
697
714
|
|
|
715
|
+
@NonNull
|
|
716
|
+
private static StringBuilder getStringBuilder() {
|
|
717
|
+
Field[] drawables = R.drawable.class.getFields();
|
|
718
|
+
StringBuilder availableResources = new StringBuilder(
|
|
719
|
+
"Available resources: "
|
|
720
|
+
);
|
|
721
|
+
for (int i = 0; i < Math.min(10, drawables.length); i++) {
|
|
722
|
+
availableResources.append(drawables[i].getName()).append(", ");
|
|
723
|
+
}
|
|
724
|
+
if (drawables.length > 10) {
|
|
725
|
+
availableResources
|
|
726
|
+
.append("... (")
|
|
727
|
+
.append(drawables.length - 10)
|
|
728
|
+
.append(" more)");
|
|
729
|
+
}
|
|
730
|
+
return availableResources;
|
|
731
|
+
}
|
|
732
|
+
|
|
698
733
|
@PluginMethod
|
|
699
734
|
public void postMessage(PluginCall call) {
|
|
700
735
|
if (webViewDialog == null) {
|