@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 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 | Description | Since |
483
- | ---------------------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ----- |
484
- | **`url`** | <code>string</code> | Target URL to load. | 0.1.0 |
485
- | **`headers`** | <code><a href="#headers">Headers</a></code> | <a href="#headers">Headers</a> to send with the request. | 0.1.0 |
486
- | **`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 |
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
- call.reject("Camera permission is required");
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
- @NonNull ComponentName name,
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
- Field[] drawables = R.drawable.class.getFields();
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.hasOption("preShowScript") &&
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.hasOption("closeModalTitle") ||
557
- call.hasOption("closeModalDescription") ||
558
- call.hasOption("closeModalOk") ||
559
- call.hasOption("closeModalCancel")
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 (call.hasOption("shareDisclaimer") && !call.hasOption("shareSubject")) {
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.hasOption("buttonNearDone")) {
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) {