@capgo/capacitor-inappbrowser 8.13.4 → 8.14.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 +88 -73
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/CapgoInAppBrowserPlugin.java +2 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/Options.java +11 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/OrientationLayoutSupport.java +41 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +261 -65
- package/dist/docs.json +17 -1
- package/dist/esm/definitions.d.ts +25 -3
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Sources/InAppBrowserPlugin/InAppBrowserPlugin.swift +7 -2
- package/ios/Sources/InAppBrowserPlugin/WKWebViewController.swift +4 -1
- package/package.json +1 -1
|
@@ -1079,6 +1079,8 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
|
|
|
1079
1079
|
options.setHandleDownloads(Boolean.TRUE.equals(call.getBoolean("handleDownloads", false)));
|
|
1080
1080
|
|
|
1081
1081
|
options.setPersistWebViewData(call.getBoolean("persistWebViewData", true));
|
|
1082
|
+
// No-op on Android: CookieManager is already process-global (API parity with iOS).
|
|
1083
|
+
options.setUseSharedDataStore(Boolean.TRUE.equals(call.getBoolean("useSharedDataStore", false)));
|
|
1082
1084
|
// Set text zoom if specified in options (default is 100)
|
|
1083
1085
|
Integer textZoom = call.getInt("textZoom");
|
|
1084
1086
|
if (textZoom != null) {
|
|
@@ -201,6 +201,8 @@ public class Options {
|
|
|
201
201
|
private boolean captureConsoleLogs = false;
|
|
202
202
|
private boolean handleDownloads = false;
|
|
203
203
|
private boolean persistWebViewData = true;
|
|
204
|
+
/** Accepted for API parity with iOS; Android cookies are already process-global. */
|
|
205
|
+
private boolean useSharedDataStore = false;
|
|
204
206
|
private InvisibilityMode invisibilityMode = InvisibilityMode.AWARE;
|
|
205
207
|
private String httpMethod = null;
|
|
206
208
|
private String httpBody = null;
|
|
@@ -315,6 +317,14 @@ public class Options {
|
|
|
315
317
|
this.persistWebViewData = persistWebViewData;
|
|
316
318
|
}
|
|
317
319
|
|
|
320
|
+
public boolean getUseSharedDataStore() {
|
|
321
|
+
return useSharedDataStore;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
public void setUseSharedDataStore(boolean useSharedDataStore) {
|
|
325
|
+
this.useSharedDataStore = useSharedDataStore;
|
|
326
|
+
}
|
|
327
|
+
|
|
318
328
|
public void setMaterialPicker(boolean materialPicker) {
|
|
319
329
|
this.materialPicker = materialPicker;
|
|
320
330
|
}
|
|
@@ -809,6 +819,7 @@ public class Options {
|
|
|
809
819
|
copy.setBlockedHosts(new ArrayList<>(getBlockedHosts()));
|
|
810
820
|
copy.setWidth(width);
|
|
811
821
|
copy.setPersistWebViewData(persistWebViewData);
|
|
822
|
+
copy.setUseSharedDataStore(useSharedDataStore);
|
|
812
823
|
copy.setHeight(height);
|
|
813
824
|
copy.setToBack(toBack);
|
|
814
825
|
copy.setTransparentBackground(transparentBackground);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package ee.forgr.capacitor_inappbrowser;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Helpers for deciding when a managed WebView dialog must relayout after a configuration
|
|
5
|
+
* change. Capacitor activities declare {@code android:configChanges}, so the host activity
|
|
6
|
+
* (and this dialog) are not recreated on rotation — layouts and window insets must be
|
|
7
|
+
* refreshed explicitly or the WebView can stop scrolling after portrait→landscape.
|
|
8
|
+
*/
|
|
9
|
+
final class OrientationLayoutSupport {
|
|
10
|
+
|
|
11
|
+
private OrientationLayoutSupport() {}
|
|
12
|
+
|
|
13
|
+
static boolean shouldRefreshBrowserLayout(
|
|
14
|
+
Integer previousOrientation,
|
|
15
|
+
Integer previousScreenWidthDp,
|
|
16
|
+
Integer previousScreenHeightDp,
|
|
17
|
+
Integer previousSmallestScreenWidthDp,
|
|
18
|
+
Integer previousDensityDpi,
|
|
19
|
+
int currentOrientation,
|
|
20
|
+
int currentScreenWidthDp,
|
|
21
|
+
int currentScreenHeightDp,
|
|
22
|
+
int currentSmallestScreenWidthDp,
|
|
23
|
+
int currentDensityDpi
|
|
24
|
+
) {
|
|
25
|
+
if (previousOrientation == null) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
previousOrientation != currentOrientation ||
|
|
31
|
+
previousScreenWidthDp == null ||
|
|
32
|
+
previousScreenWidthDp != currentScreenWidthDp ||
|
|
33
|
+
previousScreenHeightDp == null ||
|
|
34
|
+
previousScreenHeightDp != currentScreenHeightDp ||
|
|
35
|
+
previousSmallestScreenWidthDp == null ||
|
|
36
|
+
previousSmallestScreenWidthDp != currentSmallestScreenWidthDp ||
|
|
37
|
+
previousDensityDpi == null ||
|
|
38
|
+
previousDensityDpi != currentDensityDpi
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -5,10 +5,12 @@ import android.app.Activity;
|
|
|
5
5
|
import android.app.AlertDialog;
|
|
6
6
|
import android.app.Dialog;
|
|
7
7
|
import android.content.ActivityNotFoundException;
|
|
8
|
+
import android.content.ComponentCallbacks2;
|
|
8
9
|
import android.content.Context;
|
|
9
10
|
import android.content.DialogInterface;
|
|
10
11
|
import android.content.Intent;
|
|
11
12
|
import android.content.res.AssetManager;
|
|
13
|
+
import android.content.res.Configuration;
|
|
12
14
|
import android.content.res.Resources;
|
|
13
15
|
import android.graphics.Bitmap;
|
|
14
16
|
import android.graphics.Canvas;
|
|
@@ -356,6 +358,20 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
|
|
|
356
358
|
private boolean cachedTitleIconResolved;
|
|
357
359
|
private boolean isHiddenModeActive = false;
|
|
358
360
|
private boolean toolbarHideInProgress = false;
|
|
361
|
+
private boolean configurationCallbacksRegistered = false;
|
|
362
|
+
private Configuration lastConfiguration;
|
|
363
|
+
private final ComponentCallbacks2 configurationCallbacks = new ComponentCallbacks2() {
|
|
364
|
+
@Override
|
|
365
|
+
public void onConfigurationChanged(Configuration newConfig) {
|
|
366
|
+
handleConfigurationChanged(newConfig);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
@Override
|
|
370
|
+
public void onLowMemory() {}
|
|
371
|
+
|
|
372
|
+
@Override
|
|
373
|
+
public void onTrimMemory(int level) {}
|
|
374
|
+
};
|
|
359
375
|
private WindowManager.LayoutParams previousWindowAttributes;
|
|
360
376
|
private Drawable previousWindowBackground;
|
|
361
377
|
private ViewGroup.LayoutParams previousWebViewLayoutParams;
|
|
@@ -2824,6 +2840,9 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
|
|
|
2824
2840
|
showAccordingToLayerModeOrFallback();
|
|
2825
2841
|
resolveOpenWebViewIfNeeded();
|
|
2826
2842
|
}
|
|
2843
|
+
|
|
2844
|
+
// Capacitor activities handle orientation themselves; refresh dialog layout explicitly.
|
|
2845
|
+
registerConfigurationCallbacks();
|
|
2827
2846
|
}
|
|
2828
2847
|
|
|
2829
2848
|
private void applyHiddenMode() {
|
|
@@ -2974,22 +2993,11 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
|
|
|
2974
2993
|
// Check if we need Android 15+ specific fixes
|
|
2975
2994
|
boolean isAndroid15Plus = Build.VERSION.SDK_INT >= 35;
|
|
2976
2995
|
|
|
2977
|
-
// Find status bar color view and toolbar for Android 15+ specific handling
|
|
2978
|
-
View statusBarColorView = findViewById(R.id.status_bar_color_view);
|
|
2979
2996
|
View toolbarView = findViewById(R.id.tool_bar);
|
|
2980
2997
|
|
|
2981
2998
|
// Fix content browser layout height for all Android versions to allow proper scrolling
|
|
2982
2999
|
// This fixes landscape scrolling issues where bottom content is unreachable
|
|
2983
|
-
|
|
2984
|
-
if (contentBrowserLayout != null) {
|
|
2985
|
-
ViewGroup.LayoutParams layoutParams = contentBrowserLayout.getLayoutParams();
|
|
2986
|
-
if (layoutParams != null) {
|
|
2987
|
-
// Use MATCH_PARENT for height to allow proper scrolling in all orientations
|
|
2988
|
-
// The AppBarLayout's layout_behavior will handle positioning automatically
|
|
2989
|
-
layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
|
|
2990
|
-
contentBrowserLayout.setLayoutParams(layoutParams);
|
|
2991
|
-
}
|
|
2992
|
-
}
|
|
3000
|
+
ensureContentBrowserMatchParentHeight();
|
|
2993
3001
|
|
|
2994
3002
|
boolean isBlankToolbar = _options != null && TextUtils.equals(_options.getToolbarType(), "blank");
|
|
2995
3003
|
if (isBlankToolbar) {
|
|
@@ -2998,53 +3006,7 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
|
|
|
2998
3006
|
|
|
2999
3007
|
// Special handling for Android 15+
|
|
3000
3008
|
if (isAndroid15Plus && !isBlankToolbar) {
|
|
3001
|
-
|
|
3002
|
-
if (toolbarView != null && toolbarView.getParent() instanceof com.google.android.material.appbar.AppBarLayout appBarLayout) {
|
|
3003
|
-
// Remove elevation to eliminate shadows (only on Android 15+)
|
|
3004
|
-
appBarLayout.setElevation(0);
|
|
3005
|
-
appBarLayout.setStateListAnimator(null);
|
|
3006
|
-
appBarLayout.setOutlineProvider(null);
|
|
3007
|
-
|
|
3008
|
-
// Determine background color to use
|
|
3009
|
-
int backgroundColor = Color.BLACK; // Default fallback
|
|
3010
|
-
if (_options.getToolbarColor() != null && !_options.getToolbarColor().isEmpty()) {
|
|
3011
|
-
try {
|
|
3012
|
-
backgroundColor = Color.parseColor(_options.getToolbarColor());
|
|
3013
|
-
} catch (IllegalArgumentException e) {
|
|
3014
|
-
Log.e("InAppBrowser", "Invalid toolbar color, using black: " + e.getMessage());
|
|
3015
|
-
}
|
|
3016
|
-
} else {
|
|
3017
|
-
// Follow system theme if no color specified
|
|
3018
|
-
boolean isDarkTheme = isDarkThemeEnabled();
|
|
3019
|
-
backgroundColor = isDarkTheme ? Color.BLACK : Color.WHITE;
|
|
3020
|
-
}
|
|
3021
|
-
|
|
3022
|
-
// Apply fixes for Android 15+ using a delayed post
|
|
3023
|
-
final int finalBgColor = backgroundColor;
|
|
3024
|
-
_webView.post(() -> {
|
|
3025
|
-
// Get status bar height
|
|
3026
|
-
int statusBarHeight = 0;
|
|
3027
|
-
int resourceId = getContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
|
|
3028
|
-
if (resourceId > 0) {
|
|
3029
|
-
statusBarHeight = getContext().getResources().getDimensionPixelSize(resourceId);
|
|
3030
|
-
}
|
|
3031
|
-
|
|
3032
|
-
// Fix status bar view
|
|
3033
|
-
if (statusBarColorView != null) {
|
|
3034
|
-
ViewGroup.LayoutParams params = statusBarColorView.getLayoutParams();
|
|
3035
|
-
params.height = statusBarHeight;
|
|
3036
|
-
statusBarColorView.setLayoutParams(params);
|
|
3037
|
-
statusBarColorView.setBackgroundColor(finalBgColor);
|
|
3038
|
-
statusBarColorView.setVisibility(View.VISIBLE);
|
|
3039
|
-
}
|
|
3040
|
-
|
|
3041
|
-
// Fix AppBarLayout position
|
|
3042
|
-
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) appBarLayout.getLayoutParams();
|
|
3043
|
-
params.topMargin = statusBarHeight;
|
|
3044
|
-
appBarLayout.setLayoutParams(params);
|
|
3045
|
-
appBarLayout.setBackgroundColor(finalBgColor);
|
|
3046
|
-
});
|
|
3047
|
-
}
|
|
3009
|
+
refreshEdgeToEdgeChrome();
|
|
3048
3010
|
}
|
|
3049
3011
|
|
|
3050
3012
|
// Resolve insets from the dialog window root; layout children can receive already-fitted zero insets.
|
|
@@ -3152,6 +3114,232 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
|
|
|
3152
3114
|
mainHandler.postDelayed(this::applyContainerInsetsSnapshot, 1200);
|
|
3153
3115
|
}
|
|
3154
3116
|
|
|
3117
|
+
private void registerConfigurationCallbacks() {
|
|
3118
|
+
if (configurationCallbacksRegistered) {
|
|
3119
|
+
return;
|
|
3120
|
+
}
|
|
3121
|
+
|
|
3122
|
+
Context callbackContext = activity != null ? activity : _context;
|
|
3123
|
+
if (callbackContext == null) {
|
|
3124
|
+
return;
|
|
3125
|
+
}
|
|
3126
|
+
|
|
3127
|
+
lastConfiguration = new Configuration(callbackContext.getResources().getConfiguration());
|
|
3128
|
+
callbackContext.registerComponentCallbacks(configurationCallbacks);
|
|
3129
|
+
configurationCallbacksRegistered = true;
|
|
3130
|
+
}
|
|
3131
|
+
|
|
3132
|
+
private void unregisterConfigurationCallbacks() {
|
|
3133
|
+
if (!configurationCallbacksRegistered) {
|
|
3134
|
+
return;
|
|
3135
|
+
}
|
|
3136
|
+
|
|
3137
|
+
Context callbackContext = activity != null ? activity : _context;
|
|
3138
|
+
if (callbackContext != null) {
|
|
3139
|
+
try {
|
|
3140
|
+
callbackContext.unregisterComponentCallbacks(configurationCallbacks);
|
|
3141
|
+
} catch (Exception e) {
|
|
3142
|
+
Log.w("InAppBrowser", "Failed to unregister configuration callbacks: " + e.getMessage());
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
|
|
3146
|
+
configurationCallbacksRegistered = false;
|
|
3147
|
+
lastConfiguration = null;
|
|
3148
|
+
}
|
|
3149
|
+
|
|
3150
|
+
private void handleConfigurationChanged(Configuration newConfig) {
|
|
3151
|
+
if (isDismissing || _webView == null) {
|
|
3152
|
+
return;
|
|
3153
|
+
}
|
|
3154
|
+
|
|
3155
|
+
Integer previousOrientation = lastConfiguration != null ? lastConfiguration.orientation : null;
|
|
3156
|
+
Integer previousScreenWidthDp = lastConfiguration != null ? lastConfiguration.screenWidthDp : null;
|
|
3157
|
+
Integer previousScreenHeightDp = lastConfiguration != null ? lastConfiguration.screenHeightDp : null;
|
|
3158
|
+
Integer previousSmallestScreenWidthDp = lastConfiguration != null ? lastConfiguration.smallestScreenWidthDp : null;
|
|
3159
|
+
Integer previousDensityDpi = lastConfiguration != null ? lastConfiguration.densityDpi : null;
|
|
3160
|
+
|
|
3161
|
+
int currentOrientation = newConfig != null ? newConfig.orientation : (previousOrientation != null ? previousOrientation : 0);
|
|
3162
|
+
int currentScreenWidthDp =
|
|
3163
|
+
newConfig != null ? newConfig.screenWidthDp : (previousScreenWidthDp != null ? previousScreenWidthDp : 0);
|
|
3164
|
+
int currentScreenHeightDp =
|
|
3165
|
+
newConfig != null ? newConfig.screenHeightDp : (previousScreenHeightDp != null ? previousScreenHeightDp : 0);
|
|
3166
|
+
int currentSmallestScreenWidthDp =
|
|
3167
|
+
newConfig != null
|
|
3168
|
+
? newConfig.smallestScreenWidthDp
|
|
3169
|
+
: (previousSmallestScreenWidthDp != null ? previousSmallestScreenWidthDp : 0);
|
|
3170
|
+
int currentDensityDpi = newConfig != null ? newConfig.densityDpi : (previousDensityDpi != null ? previousDensityDpi : 0);
|
|
3171
|
+
|
|
3172
|
+
boolean shouldRefresh = OrientationLayoutSupport.shouldRefreshBrowserLayout(
|
|
3173
|
+
previousOrientation,
|
|
3174
|
+
previousScreenWidthDp,
|
|
3175
|
+
previousScreenHeightDp,
|
|
3176
|
+
previousSmallestScreenWidthDp,
|
|
3177
|
+
previousDensityDpi,
|
|
3178
|
+
currentOrientation,
|
|
3179
|
+
currentScreenWidthDp,
|
|
3180
|
+
currentScreenHeightDp,
|
|
3181
|
+
currentSmallestScreenWidthDp,
|
|
3182
|
+
currentDensityDpi
|
|
3183
|
+
);
|
|
3184
|
+
|
|
3185
|
+
if (newConfig != null) {
|
|
3186
|
+
lastConfiguration = new Configuration(newConfig);
|
|
3187
|
+
}
|
|
3188
|
+
|
|
3189
|
+
if (!shouldRefresh) {
|
|
3190
|
+
return;
|
|
3191
|
+
}
|
|
3192
|
+
|
|
3193
|
+
if (Looper.myLooper() == Looper.getMainLooper()) {
|
|
3194
|
+
refreshLayoutForConfigurationChange();
|
|
3195
|
+
} else {
|
|
3196
|
+
mainHandler.post(this::refreshLayoutForConfigurationChange);
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
|
|
3200
|
+
/**
|
|
3201
|
+
* Capacitor keeps the host activity alive across orientation changes. Re-apply fullscreen
|
|
3202
|
+
* window dimensions, system chrome, and safe-area insets so the WebView stays scrollable
|
|
3203
|
+
* after portrait↔landscape transitions.
|
|
3204
|
+
*/
|
|
3205
|
+
private void refreshLayoutForConfigurationChange() {
|
|
3206
|
+
if (isDismissing || _webView == null) {
|
|
3207
|
+
return;
|
|
3208
|
+
}
|
|
3209
|
+
|
|
3210
|
+
if (isHiddenModeActive) {
|
|
3211
|
+
requestSafeAreaInsets();
|
|
3212
|
+
return;
|
|
3213
|
+
}
|
|
3214
|
+
|
|
3215
|
+
if (backLayerActive) {
|
|
3216
|
+
applyBackLayerDimensions();
|
|
3217
|
+
} else {
|
|
3218
|
+
applyDimensions();
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
ensureContentBrowserMatchParentHeight();
|
|
3222
|
+
|
|
3223
|
+
boolean isBlankToolbar = _options != null && TextUtils.equals(_options.getToolbarType(), "blank");
|
|
3224
|
+
if (isBlankToolbar) {
|
|
3225
|
+
configureBlankToolbarLayout();
|
|
3226
|
+
} else if (Build.VERSION.SDK_INT >= 35) {
|
|
3227
|
+
refreshEdgeToEdgeChrome();
|
|
3228
|
+
} else {
|
|
3229
|
+
refreshStatusBarColorViewHeight();
|
|
3230
|
+
}
|
|
3231
|
+
|
|
3232
|
+
View coordinator = findViewById(R.id.coordinator_layout);
|
|
3233
|
+
if (coordinator != null) {
|
|
3234
|
+
coordinator.requestLayout();
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3237
|
+
if (swipeRefreshLayout != null) {
|
|
3238
|
+
swipeRefreshLayout.requestLayout();
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
_webView.requestLayout();
|
|
3242
|
+
_webView.invalidate();
|
|
3243
|
+
requestSafeAreaInsets();
|
|
3244
|
+
|
|
3245
|
+
mainHandler.post(this::applyContainerInsetsSnapshot);
|
|
3246
|
+
mainHandler.postDelayed(this::applyContainerInsetsSnapshot, 100);
|
|
3247
|
+
mainHandler.postDelayed(this::applyContainerInsetsSnapshot, 300);
|
|
3248
|
+
|
|
3249
|
+
_webView.post(() -> {
|
|
3250
|
+
if (_webView == null) {
|
|
3251
|
+
return;
|
|
3252
|
+
}
|
|
3253
|
+
_webView.evaluateJavascript("(function(){window.dispatchEvent(new Event('resize'));})();", null);
|
|
3254
|
+
});
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
private void ensureContentBrowserMatchParentHeight() {
|
|
3258
|
+
View contentBrowserLayout = findViewById(R.id.content_browser_layout);
|
|
3259
|
+
if (contentBrowserLayout == null) {
|
|
3260
|
+
return;
|
|
3261
|
+
}
|
|
3262
|
+
|
|
3263
|
+
ViewGroup.LayoutParams layoutParams = contentBrowserLayout.getLayoutParams();
|
|
3264
|
+
if (layoutParams == null) {
|
|
3265
|
+
return;
|
|
3266
|
+
}
|
|
3267
|
+
|
|
3268
|
+
layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
|
|
3269
|
+
contentBrowserLayout.setLayoutParams(layoutParams);
|
|
3270
|
+
}
|
|
3271
|
+
|
|
3272
|
+
private void refreshStatusBarColorViewHeight() {
|
|
3273
|
+
View statusBarColorView = findViewById(R.id.status_bar_color_view);
|
|
3274
|
+
if (statusBarColorView == null) {
|
|
3275
|
+
return;
|
|
3276
|
+
}
|
|
3277
|
+
|
|
3278
|
+
int statusBarHeight = getSystemStatusBarHeight();
|
|
3279
|
+
ViewGroup.LayoutParams params = statusBarColorView.getLayoutParams();
|
|
3280
|
+
if (params == null) {
|
|
3281
|
+
return;
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
params.height = statusBarHeight;
|
|
3285
|
+
statusBarColorView.setLayoutParams(params);
|
|
3286
|
+
statusBarColorView.requestLayout();
|
|
3287
|
+
}
|
|
3288
|
+
|
|
3289
|
+
private void refreshEdgeToEdgeChrome() {
|
|
3290
|
+
if (_webView == null || _options == null) {
|
|
3291
|
+
return;
|
|
3292
|
+
}
|
|
3293
|
+
|
|
3294
|
+
View statusBarColorView = findViewById(R.id.status_bar_color_view);
|
|
3295
|
+
View toolbarView = findViewById(R.id.tool_bar);
|
|
3296
|
+
if (toolbarView == null || !(toolbarView.getParent() instanceof com.google.android.material.appbar.AppBarLayout appBarLayout)) {
|
|
3297
|
+
refreshStatusBarColorViewHeight();
|
|
3298
|
+
return;
|
|
3299
|
+
}
|
|
3300
|
+
|
|
3301
|
+
appBarLayout.setElevation(0);
|
|
3302
|
+
appBarLayout.setStateListAnimator(null);
|
|
3303
|
+
appBarLayout.setOutlineProvider(null);
|
|
3304
|
+
|
|
3305
|
+
int backgroundColor = Color.BLACK;
|
|
3306
|
+
if (_options.getToolbarColor() != null && !_options.getToolbarColor().isEmpty()) {
|
|
3307
|
+
try {
|
|
3308
|
+
backgroundColor = Color.parseColor(_options.getToolbarColor());
|
|
3309
|
+
} catch (IllegalArgumentException e) {
|
|
3310
|
+
Log.e("InAppBrowser", "Invalid toolbar color, using black: " + e.getMessage());
|
|
3311
|
+
}
|
|
3312
|
+
} else {
|
|
3313
|
+
backgroundColor = isDarkThemeEnabled() ? Color.BLACK : Color.WHITE;
|
|
3314
|
+
}
|
|
3315
|
+
|
|
3316
|
+
final int finalBgColor = backgroundColor;
|
|
3317
|
+
_webView.post(() -> {
|
|
3318
|
+
if (_webView == null) {
|
|
3319
|
+
return;
|
|
3320
|
+
}
|
|
3321
|
+
|
|
3322
|
+
int statusBarHeight = getSystemStatusBarHeight();
|
|
3323
|
+
|
|
3324
|
+
if (statusBarColorView != null) {
|
|
3325
|
+
ViewGroup.LayoutParams params = statusBarColorView.getLayoutParams();
|
|
3326
|
+
if (params != null) {
|
|
3327
|
+
params.height = statusBarHeight;
|
|
3328
|
+
statusBarColorView.setLayoutParams(params);
|
|
3329
|
+
}
|
|
3330
|
+
statusBarColorView.setBackgroundColor(finalBgColor);
|
|
3331
|
+
statusBarColorView.setVisibility(View.VISIBLE);
|
|
3332
|
+
}
|
|
3333
|
+
|
|
3334
|
+
ViewGroup.LayoutParams appBarParams = appBarLayout.getLayoutParams();
|
|
3335
|
+
if (appBarParams instanceof ViewGroup.MarginLayoutParams marginParams) {
|
|
3336
|
+
marginParams.topMargin = statusBarHeight;
|
|
3337
|
+
appBarLayout.setLayoutParams(marginParams);
|
|
3338
|
+
}
|
|
3339
|
+
appBarLayout.setBackgroundColor(finalBgColor);
|
|
3340
|
+
});
|
|
3341
|
+
}
|
|
3342
|
+
|
|
3155
3343
|
private void applySafeAreaMargins(
|
|
3156
3344
|
Insets bars,
|
|
3157
3345
|
Insets navigationBars,
|
|
@@ -5859,6 +6047,7 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
|
|
|
5859
6047
|
|
|
5860
6048
|
@Override
|
|
5861
6049
|
public void dismiss() {
|
|
6050
|
+
unregisterConfigurationCallbacks();
|
|
5862
6051
|
scheduleHostWebViewInsetRestore();
|
|
5863
6052
|
detachBackLayer();
|
|
5864
6053
|
|
|
@@ -6969,7 +7158,12 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
|
|
|
6969
7158
|
Integer x = _options.getX();
|
|
6970
7159
|
Integer y = _options.getY();
|
|
6971
7160
|
|
|
6972
|
-
|
|
7161
|
+
Window window = getWindow();
|
|
7162
|
+
if (window == null) {
|
|
7163
|
+
return;
|
|
7164
|
+
}
|
|
7165
|
+
|
|
7166
|
+
WindowManager.LayoutParams params = window.getAttributes();
|
|
6973
7167
|
|
|
6974
7168
|
// If both width and height are specified, use custom dimensions
|
|
6975
7169
|
if (width != null && height != null) {
|
|
@@ -6979,6 +7173,7 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
|
|
|
6979
7173
|
params.x = (x != null) ? (int) getPixels(x) : 0;
|
|
6980
7174
|
params.y = (y != null) ? (int) getPixels(y) : 0;
|
|
6981
7175
|
params.gravity = Gravity.TOP | Gravity.START;
|
|
7176
|
+
window.setAttributes(params);
|
|
6982
7177
|
} else if (height != null && width == null) {
|
|
6983
7178
|
// If only height is specified, use custom height with fullscreen width
|
|
6984
7179
|
params.gravity = Gravity.TOP | Gravity.LEFT;
|
|
@@ -6987,15 +7182,16 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
|
|
|
6987
7182
|
params.x = 0;
|
|
6988
7183
|
params.y = (y != null) ? (int) getPixels(y) : 0;
|
|
6989
7184
|
params.gravity = Gravity.TOP | Gravity.START;
|
|
7185
|
+
window.setAttributes(params);
|
|
6990
7186
|
} else {
|
|
6991
|
-
// Default to fullscreen
|
|
6992
|
-
|
|
6993
|
-
params.height = WindowManager.LayoutParams.MATCH_PARENT;
|
|
7187
|
+
// Default to fullscreen. Prefer setLayout so MATCH_PARENT is not replaced by
|
|
7188
|
+
// previously resolved portrait/landscape pixel sizes after a configuration change.
|
|
6994
7189
|
params.x = 0;
|
|
6995
7190
|
params.y = 0;
|
|
7191
|
+
params.gravity = Gravity.TOP | Gravity.START;
|
|
7192
|
+
window.setAttributes(params);
|
|
7193
|
+
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
|
|
6996
7194
|
}
|
|
6997
|
-
|
|
6998
|
-
getWindow().setAttributes(params);
|
|
6999
7195
|
}
|
|
7000
7196
|
|
|
7001
7197
|
/**
|
package/dist/docs.json
CHANGED
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
"text": "8.6.36"
|
|
130
130
|
}
|
|
131
131
|
],
|
|
132
|
-
"docs": "Clear all browsing data from InAppBrowser-managed webviews and the plugin-owned data store.\n\nThis removes cookies, disk cache, memory cache, local storage, session storage, IndexedDB,\nWebSQL where supported, form data, and HTTP auth data for InAppBrowser only.\n\nIt does **not** clear the Capacitor/Ionic host WebView stores. On iOS 17+, InAppBrowser uses a\ndedicated persistent `WKWebsiteDataStore` so host and browser data stay isolated. On Android
|
|
132
|
+
"docs": "Clear all browsing data from InAppBrowser-managed webviews and the plugin-owned data store.\n\nThis removes cookies, disk cache, memory cache, local storage, session storage, IndexedDB,\nWebSQL where supported, form data, and HTTP auth data for InAppBrowser only.\n\nIt does **not** clear the Capacitor/Ionic host WebView stores. On iOS 17+, InAppBrowser uses a\ndedicated persistent `WKWebsiteDataStore` so host and browser data stay isolated (unless\n`useSharedDataStore: true` was set on `openWebView`). On Android, process-global `CookieManager`\n/ `WebStorage` are shared with the host WebView and are not wiped by this method; open managed\nWebViews still clear per-view cache/history and page storage.",
|
|
133
133
|
"complexTypes": [],
|
|
134
134
|
"slug": "clearallbrowsingdata"
|
|
135
135
|
},
|
|
@@ -1584,6 +1584,22 @@
|
|
|
1584
1584
|
"complexTypes": [],
|
|
1585
1585
|
"type": "boolean | undefined"
|
|
1586
1586
|
},
|
|
1587
|
+
{
|
|
1588
|
+
"name": "useSharedDataStore",
|
|
1589
|
+
"tags": [
|
|
1590
|
+
{
|
|
1591
|
+
"text": "false",
|
|
1592
|
+
"name": "default"
|
|
1593
|
+
},
|
|
1594
|
+
{
|
|
1595
|
+
"text": "8.13.6",
|
|
1596
|
+
"name": "since"
|
|
1597
|
+
}
|
|
1598
|
+
],
|
|
1599
|
+
"docs": "Share the host Capacitor WebView's website data store (cookies, local storage, etc.).\n\nOn iOS 17+, InAppBrowser uses an isolated plugin-owned `WKWebsiteDataStore` by default so host\nand browser data stay separate. Set this to `true` to use `WKWebsiteDataStore.default()` instead,\nwhich shares session cookies with the Capacitor host WebView. Useful for SSO / OIDC silent login\nwhen the IdP session was established in the main app WebView.\n\nRequires `persistWebViewData: true` (the default). When `persistWebViewData` is false, a\nnon-persistent store is used and this option has no effect.\n\nOn Android this is a no-op: cookies are already process-global via `CookieManager`.\nOn Web this is a no-op.\n\nWarning: clearing cookies/cache for a webview opened with this flag can affect the host WebView\non iOS, because both share the same store. `clearAllBrowsingData()` still skips the host store.",
|
|
1600
|
+
"complexTypes": [],
|
|
1601
|
+
"type": "boolean | undefined"
|
|
1602
|
+
},
|
|
1587
1603
|
{
|
|
1588
1604
|
"name": "clientCertificate",
|
|
1589
1605
|
"tags": [
|
|
@@ -727,6 +727,27 @@ export interface OpenWebViewOptions {
|
|
|
727
727
|
* @since 8.6.36
|
|
728
728
|
*/
|
|
729
729
|
persistWebViewData?: boolean;
|
|
730
|
+
/**
|
|
731
|
+
* Share the host Capacitor WebView's website data store (cookies, local storage, etc.).
|
|
732
|
+
*
|
|
733
|
+
* On iOS 17+, InAppBrowser uses an isolated plugin-owned `WKWebsiteDataStore` by default so host
|
|
734
|
+
* and browser data stay separate. Set this to `true` to use `WKWebsiteDataStore.default()` instead,
|
|
735
|
+
* which shares session cookies with the Capacitor host WebView. Useful for SSO / OIDC silent login
|
|
736
|
+
* when the IdP session was established in the main app WebView.
|
|
737
|
+
*
|
|
738
|
+
* Requires `persistWebViewData: true` (the default). When `persistWebViewData` is false, a
|
|
739
|
+
* non-persistent store is used and this option has no effect.
|
|
740
|
+
*
|
|
741
|
+
* On Android this is a no-op: cookies are already process-global via `CookieManager`.
|
|
742
|
+
* On Web this is a no-op.
|
|
743
|
+
*
|
|
744
|
+
* Warning: clearing cookies/cache for a webview opened with this flag can affect the host WebView
|
|
745
|
+
* on iOS, because both share the same store. `clearAllBrowsingData()` still skips the host store.
|
|
746
|
+
*
|
|
747
|
+
* @default false
|
|
748
|
+
* @since 8.13.6
|
|
749
|
+
*/
|
|
750
|
+
useSharedDataStore?: boolean;
|
|
730
751
|
/**
|
|
731
752
|
* Controls Android TLS client certificate prompts during HTTPS handshakes.
|
|
732
753
|
* Use `prompt` to show the system certificate picker; omit or use `none` to cancel silently (default).
|
|
@@ -1400,9 +1421,10 @@ export interface InAppBrowserPlugin {
|
|
|
1400
1421
|
* WebSQL where supported, form data, and HTTP auth data for InAppBrowser only.
|
|
1401
1422
|
*
|
|
1402
1423
|
* It does **not** clear the Capacitor/Ionic host WebView stores. On iOS 17+, InAppBrowser uses a
|
|
1403
|
-
* dedicated persistent `WKWebsiteDataStore` so host and browser data stay isolated
|
|
1404
|
-
*
|
|
1405
|
-
*
|
|
1424
|
+
* dedicated persistent `WKWebsiteDataStore` so host and browser data stay isolated (unless
|
|
1425
|
+
* `useSharedDataStore: true` was set on `openWebView`). On Android, process-global `CookieManager`
|
|
1426
|
+
* / `WebStorage` are shared with the host WebView and are not wiped by this method; open managed
|
|
1427
|
+
* WebViews still clear per-view cache/history and page storage.
|
|
1406
1428
|
*
|
|
1407
1429
|
* @since 8.6.36
|
|
1408
1430
|
*/
|