@capacitor/android 8.0.0-alpha.3 → 8.0.0-beta.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/capacitor/build.gradle +6 -8
- package/capacitor/src/main/assets/native-bridge.js +1 -1
- package/capacitor/src/main/java/com/getcapacitor/Bridge.java +1 -1
- package/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java +1 -6
- package/capacitor/src/main/java/com/getcapacitor/CapConfig.java +0 -8
- package/capacitor/src/main/java/com/getcapacitor/CapacitorWebView.java +0 -32
- package/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java +220 -0
- package/package.json +2 -2
package/capacitor/build.gradle
CHANGED
|
@@ -13,12 +13,11 @@ ext {
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
buildscript {
|
|
16
|
-
ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '2.2.20'
|
|
17
16
|
repositories {
|
|
18
17
|
google()
|
|
19
18
|
mavenCentral()
|
|
20
19
|
maven {
|
|
21
|
-
url "https://plugins.gradle.org/m2/"
|
|
20
|
+
url = "https://plugins.gradle.org/m2/"
|
|
22
21
|
}
|
|
23
22
|
}
|
|
24
23
|
dependencies {
|
|
@@ -41,8 +40,8 @@ if (System.getenv("CAP_PUBLISH") == "true") {
|
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
android {
|
|
44
|
-
namespace "com.getcapacitor.android"
|
|
45
|
-
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 36
|
|
43
|
+
namespace = "com.getcapacitor.android"
|
|
44
|
+
compileSdk = project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 36
|
|
46
45
|
defaultConfig {
|
|
47
46
|
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 24
|
|
48
47
|
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 36
|
|
@@ -59,9 +58,9 @@ android {
|
|
|
59
58
|
}
|
|
60
59
|
lintOptions {
|
|
61
60
|
baseline file("lint-baseline.xml")
|
|
62
|
-
abortOnError true
|
|
63
|
-
warningsAsErrors true
|
|
64
|
-
lintConfig file('lint.xml')
|
|
61
|
+
abortOnError = true
|
|
62
|
+
warningsAsErrors = true
|
|
63
|
+
lintConfig = file('lint.xml')
|
|
65
64
|
}
|
|
66
65
|
compileOptions {
|
|
67
66
|
sourceCompatibility JavaVersion.VERSION_21
|
|
@@ -79,7 +78,6 @@ repositories {
|
|
|
79
78
|
|
|
80
79
|
dependencies {
|
|
81
80
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
82
|
-
implementation platform("org.jetbrains.kotlin:kotlin-bom:$kotlin_version")
|
|
83
81
|
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
84
82
|
implementation "androidx.core:core:$androidxCoreVersion"
|
|
85
83
|
implementation "androidx.activity:activity:$androidxActivityVersion"
|
|
@@ -655,6 +655,7 @@ public class Bridge {
|
|
|
655
655
|
this.registerPlugin(com.getcapacitor.plugin.CapacitorCookies.class);
|
|
656
656
|
this.registerPlugin(com.getcapacitor.plugin.WebView.class);
|
|
657
657
|
this.registerPlugin(com.getcapacitor.plugin.CapacitorHttp.class);
|
|
658
|
+
this.registerPlugin(com.getcapacitor.plugin.SystemBars.class);
|
|
658
659
|
|
|
659
660
|
for (Class<? extends Plugin> pluginClass : this.initialPlugins) {
|
|
660
661
|
this.registerPlugin(pluginClass);
|
|
@@ -1610,7 +1611,6 @@ public class Bridge {
|
|
|
1610
1611
|
|
|
1611
1612
|
if (webView instanceof CapacitorWebView capacitorWebView) {
|
|
1612
1613
|
capacitorWebView.setBridge(bridge);
|
|
1613
|
-
capacitorWebView.edgeToEdgeHandler(bridge);
|
|
1614
1614
|
}
|
|
1615
1615
|
|
|
1616
1616
|
bridge.setCordovaWebView(mockWebView);
|
|
@@ -447,12 +447,7 @@ public class BridgeWebChromeClient extends WebChromeClient {
|
|
|
447
447
|
}
|
|
448
448
|
|
|
449
449
|
public boolean isValidMsg(String msg) {
|
|
450
|
-
return !(
|
|
451
|
-
msg.contains("%cresult %c") ||
|
|
452
|
-
(msg.contains("%cnative %c")) ||
|
|
453
|
-
msg.equalsIgnoreCase("[object Object]") ||
|
|
454
|
-
msg.equalsIgnoreCase("console.groupEnd")
|
|
455
|
-
);
|
|
450
|
+
return !(msg.contains("%cresult %c") || (msg.contains("%cnative %c")) || msg.equalsIgnoreCase("console.groupEnd"));
|
|
456
451
|
}
|
|
457
452
|
|
|
458
453
|
private Uri createImageFileUri() throws IOException {
|
|
@@ -54,7 +54,6 @@ public class CapConfig {
|
|
|
54
54
|
private String errorPath;
|
|
55
55
|
private boolean zoomableWebView = false;
|
|
56
56
|
private boolean resolveServiceWorkerRequests = true;
|
|
57
|
-
private String adjustMarginsForEdgeToEdge = "disable";
|
|
58
57
|
|
|
59
58
|
// Embedded
|
|
60
59
|
private String startPath;
|
|
@@ -182,7 +181,6 @@ public class CapConfig {
|
|
|
182
181
|
this.errorPath = builder.errorPath;
|
|
183
182
|
this.zoomableWebView = builder.zoomableWebView;
|
|
184
183
|
this.resolveServiceWorkerRequests = builder.resolveServiceWorkerRequests;
|
|
185
|
-
this.adjustMarginsForEdgeToEdge = builder.adjustMarginsForEdgeToEdge;
|
|
186
184
|
|
|
187
185
|
// Embedded
|
|
188
186
|
this.startPath = builder.startPath;
|
|
@@ -288,7 +286,6 @@ public class CapConfig {
|
|
|
288
286
|
webContentsDebuggingEnabled = JSONUtils.getBoolean(configJSON, "android.webContentsDebuggingEnabled", isDebug);
|
|
289
287
|
zoomableWebView = JSONUtils.getBoolean(configJSON, "android.zoomEnabled", JSONUtils.getBoolean(configJSON, "zoomEnabled", false));
|
|
290
288
|
resolveServiceWorkerRequests = JSONUtils.getBoolean(configJSON, "android.resolveServiceWorkerRequests", true);
|
|
291
|
-
adjustMarginsForEdgeToEdge = JSONUtils.getString(configJSON, "android.adjustMarginsForEdgeToEdge", "disable");
|
|
292
289
|
|
|
293
290
|
String logBehavior = JSONUtils.getString(
|
|
294
291
|
configJSON,
|
|
@@ -405,10 +402,6 @@ public class CapConfig {
|
|
|
405
402
|
return useLegacyBridge;
|
|
406
403
|
}
|
|
407
404
|
|
|
408
|
-
public String adjustMarginsForEdgeToEdge() {
|
|
409
|
-
return adjustMarginsForEdgeToEdge;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
405
|
public int getMinWebViewVersion() {
|
|
413
406
|
if (minWebViewVersion < MINIMUM_ANDROID_WEBVIEW_VERSION) {
|
|
414
407
|
Logger.warn("Specified minimum webview version is too low, defaulting to " + MINIMUM_ANDROID_WEBVIEW_VERSION);
|
|
@@ -589,7 +582,6 @@ public class CapConfig {
|
|
|
589
582
|
private int minHuaweiWebViewVersion = DEFAULT_HUAWEI_WEBVIEW_VERSION;
|
|
590
583
|
private boolean zoomableWebView = false;
|
|
591
584
|
private boolean resolveServiceWorkerRequests = true;
|
|
592
|
-
private String adjustMarginsForEdgeToEdge = "disable";
|
|
593
585
|
|
|
594
586
|
// Embedded
|
|
595
587
|
private String startPath = null;
|
|
@@ -54,36 +54,4 @@ public class CapacitorWebView extends WebView {
|
|
|
54
54
|
}
|
|
55
55
|
return super.dispatchKeyEvent(event);
|
|
56
56
|
}
|
|
57
|
-
|
|
58
|
-
public void edgeToEdgeHandler(Bridge bridge) {
|
|
59
|
-
String configEdgeToEdge = bridge.getConfig().adjustMarginsForEdgeToEdge();
|
|
60
|
-
|
|
61
|
-
if (configEdgeToEdge.equals("disable")) return;
|
|
62
|
-
|
|
63
|
-
boolean autoMargins = false;
|
|
64
|
-
boolean forceMargins = configEdgeToEdge.equals("force");
|
|
65
|
-
|
|
66
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && configEdgeToEdge.equals("auto")) {
|
|
67
|
-
TypedValue value = new TypedValue();
|
|
68
|
-
boolean foundOptOut = getContext().getTheme().resolveAttribute(android.R.attr.windowOptOutEdgeToEdgeEnforcement, value, true);
|
|
69
|
-
boolean optOutValue = value.data != 0; // value is set to -1 on true as of Android 15, so we have to do this.
|
|
70
|
-
|
|
71
|
-
autoMargins = !(foundOptOut && optOutValue);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (forceMargins || autoMargins) {
|
|
75
|
-
ViewCompat.setOnApplyWindowInsetsListener(this, (v, windowInsets) -> {
|
|
76
|
-
Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
|
|
77
|
-
MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
|
|
78
|
-
mlp.leftMargin = insets.left;
|
|
79
|
-
mlp.bottomMargin = insets.bottom;
|
|
80
|
-
mlp.rightMargin = insets.right;
|
|
81
|
-
mlp.topMargin = insets.top;
|
|
82
|
-
v.setLayoutParams(mlp);
|
|
83
|
-
|
|
84
|
-
// Don't pass window insets to children
|
|
85
|
-
return WindowInsetsCompat.CONSUMED;
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
57
|
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
package com.getcapacitor.plugin;
|
|
2
|
+
|
|
3
|
+
import android.content.pm.PackageInfo;
|
|
4
|
+
import android.content.res.Configuration;
|
|
5
|
+
import android.view.View;
|
|
6
|
+
import android.view.Window;
|
|
7
|
+
import androidx.core.graphics.Insets;
|
|
8
|
+
import androidx.core.view.ViewCompat;
|
|
9
|
+
import androidx.core.view.WindowCompat;
|
|
10
|
+
import androidx.core.view.WindowInsetsCompat;
|
|
11
|
+
import androidx.core.view.WindowInsetsControllerCompat;
|
|
12
|
+
import androidx.webkit.WebViewCompat;
|
|
13
|
+
import com.getcapacitor.Plugin;
|
|
14
|
+
import com.getcapacitor.PluginCall;
|
|
15
|
+
import com.getcapacitor.PluginMethod;
|
|
16
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
17
|
+
import java.util.Locale;
|
|
18
|
+
import java.util.regex.Matcher;
|
|
19
|
+
import java.util.regex.Pattern;
|
|
20
|
+
|
|
21
|
+
@CapacitorPlugin
|
|
22
|
+
public class SystemBars extends Plugin {
|
|
23
|
+
|
|
24
|
+
static final String STYLE_LIGHT = "LIGHT";
|
|
25
|
+
static final String STYLE_DARK = "DARK";
|
|
26
|
+
static final String STYLE_DEFAULT = "DEFAULT";
|
|
27
|
+
static final String BAR_STATUS_BAR = "StatusBar";
|
|
28
|
+
static final String BAR_GESTURE_BAR = "NavigationBar";
|
|
29
|
+
|
|
30
|
+
static final String viewportMetaJSFunction = """
|
|
31
|
+
function capacitorSystemBarsCheckMetaViewport() {
|
|
32
|
+
const meta = document.querySelectorAll("meta[name=viewport]");
|
|
33
|
+
if (meta.length == 0) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
// get the last found meta viewport tag
|
|
37
|
+
const metaContent = meta[meta.length - 1].content;
|
|
38
|
+
return metaContent.includes("viewport-fit=cover");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
capacitorSystemBarsCheckMetaViewport();
|
|
42
|
+
""";
|
|
43
|
+
|
|
44
|
+
@Override
|
|
45
|
+
public void load() {
|
|
46
|
+
super.load();
|
|
47
|
+
initSystemBars();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private boolean hasFixedWebView() {
|
|
51
|
+
PackageInfo packageInfo = WebViewCompat.getCurrentWebViewPackage(bridge.getContext());
|
|
52
|
+
Pattern pattern = Pattern.compile("(\\d+)");
|
|
53
|
+
Matcher matcher = pattern.matcher(packageInfo.versionName);
|
|
54
|
+
|
|
55
|
+
if (!matcher.find()) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
String majorVersionStr = matcher.group(0);
|
|
60
|
+
int majorVersion = Integer.parseInt(majorVersionStr);
|
|
61
|
+
|
|
62
|
+
return majorVersion >= 140;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private void initSystemBars() {
|
|
66
|
+
String style = getConfig().getString("style", STYLE_DEFAULT).toUpperCase(Locale.US);
|
|
67
|
+
boolean hidden = getConfig().getBoolean("hidden", false);
|
|
68
|
+
boolean disableCSSInsets = getConfig().getBoolean("disableInsets", false);
|
|
69
|
+
|
|
70
|
+
this.bridge.getWebView().evaluateJavascript(viewportMetaJSFunction, (res) -> {
|
|
71
|
+
boolean hasMetaViewportCover = res.equals("true");
|
|
72
|
+
if (!disableCSSInsets) {
|
|
73
|
+
setupSafeAreaInsets(this.hasFixedWebView(), hasMetaViewportCover);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
getBridge().executeOnMainThread(() -> {
|
|
78
|
+
setStyle(style, "");
|
|
79
|
+
setHidden(hidden, "");
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@PluginMethod
|
|
84
|
+
public void setStyle(final PluginCall call) {
|
|
85
|
+
String bar = call.getString("bar", "");
|
|
86
|
+
String style = call.getString("style", STYLE_DEFAULT);
|
|
87
|
+
|
|
88
|
+
getBridge().executeOnMainThread(() -> {
|
|
89
|
+
setStyle(style, bar);
|
|
90
|
+
call.resolve();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@PluginMethod
|
|
95
|
+
public void show(final PluginCall call) {
|
|
96
|
+
String bar = call.getString("bar", "");
|
|
97
|
+
|
|
98
|
+
getBridge().executeOnMainThread(() -> {
|
|
99
|
+
setHidden(false, bar);
|
|
100
|
+
call.resolve();
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@PluginMethod
|
|
105
|
+
public void hide(final PluginCall call) {
|
|
106
|
+
String bar = call.getString("bar", "");
|
|
107
|
+
|
|
108
|
+
getBridge().executeOnMainThread(() -> {
|
|
109
|
+
setHidden(true, bar);
|
|
110
|
+
call.resolve();
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@PluginMethod
|
|
115
|
+
public void setAnimation(final PluginCall call) {
|
|
116
|
+
call.resolve();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private void setupSafeAreaInsets(boolean hasFixedWebView, boolean hasMetaViewportCover) {
|
|
120
|
+
ViewCompat.setOnApplyWindowInsetsListener((View) getBridge().getWebView().getParent(), (v, insets) -> {
|
|
121
|
+
if (hasFixedWebView && hasMetaViewportCover) {
|
|
122
|
+
return insets;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Insets safeArea = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
|
|
126
|
+
Insets imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime());
|
|
127
|
+
boolean keyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
|
|
128
|
+
|
|
129
|
+
int bottomInsets = safeArea.bottom;
|
|
130
|
+
|
|
131
|
+
if (keyboardVisible) {
|
|
132
|
+
// When https://issues.chromium.org/issues/457682720 is fixed and released,
|
|
133
|
+
// add behind a WebView version check
|
|
134
|
+
bottomInsets = imeInsets.bottom - bottomInsets;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
injectSafeAreaCSS(safeArea.top, safeArea.right, bottomInsets, safeArea.left);
|
|
138
|
+
|
|
139
|
+
return WindowInsetsCompat.CONSUMED;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private void injectSafeAreaCSS(int top, int right, int bottom, int left) {
|
|
144
|
+
// Convert pixels to density-independent pixels
|
|
145
|
+
float density = getActivity().getResources().getDisplayMetrics().density;
|
|
146
|
+
float topPx = top / density;
|
|
147
|
+
float rightPx = right / density;
|
|
148
|
+
float bottomPx = bottom / density;
|
|
149
|
+
float leftPx = left / density;
|
|
150
|
+
|
|
151
|
+
// Execute JavaScript to inject the CSS
|
|
152
|
+
getBridge().executeOnMainThread(() -> {
|
|
153
|
+
if (bridge != null && bridge.getWebView() != null) {
|
|
154
|
+
String script = String.format(
|
|
155
|
+
Locale.US,
|
|
156
|
+
"""
|
|
157
|
+
try {
|
|
158
|
+
document.documentElement.style.setProperty("--safe-area-inset-top", "%dpx");
|
|
159
|
+
document.documentElement.style.setProperty("--safe-area-inset-right", "%dpx");
|
|
160
|
+
document.documentElement.style.setProperty("--safe-area-inset-bottom", "%dpx");
|
|
161
|
+
document.documentElement.style.setProperty("--safe-area-inset-left", "%dpx");
|
|
162
|
+
} catch(e) { console.error('Error injecting safe area CSS:', e); }
|
|
163
|
+
""",
|
|
164
|
+
(int) topPx,
|
|
165
|
+
(int) rightPx,
|
|
166
|
+
(int) bottomPx,
|
|
167
|
+
(int) leftPx
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
bridge.getWebView().evaluateJavascript(script, null);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private void setStyle(String style, String bar) {
|
|
176
|
+
if (style.equals(STYLE_DEFAULT)) {
|
|
177
|
+
style = getStyleForTheme();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
Window window = getActivity().getWindow();
|
|
181
|
+
WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.getInsetsController(window, window.getDecorView());
|
|
182
|
+
if (bar.isEmpty() || bar.equals(BAR_STATUS_BAR)) {
|
|
183
|
+
windowInsetsControllerCompat.setAppearanceLightStatusBars(!style.equals(STYLE_DARK));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (bar.isEmpty() || bar.equals(BAR_GESTURE_BAR)) {
|
|
187
|
+
windowInsetsControllerCompat.setAppearanceLightNavigationBars(!style.equals(STYLE_DARK));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private void setHidden(boolean hide, String bar) {
|
|
192
|
+
Window window = getActivity().getWindow();
|
|
193
|
+
WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.getInsetsController(window, window.getDecorView());
|
|
194
|
+
|
|
195
|
+
if (hide) {
|
|
196
|
+
if (bar.isEmpty() || bar.equals(BAR_STATUS_BAR)) {
|
|
197
|
+
windowInsetsControllerCompat.hide(WindowInsetsCompat.Type.statusBars());
|
|
198
|
+
}
|
|
199
|
+
if (bar.isEmpty() || bar.equals(BAR_GESTURE_BAR)) {
|
|
200
|
+
windowInsetsControllerCompat.hide(WindowInsetsCompat.Type.navigationBars());
|
|
201
|
+
}
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (bar.isEmpty() || bar.equals(BAR_STATUS_BAR)) {
|
|
206
|
+
windowInsetsControllerCompat.show(WindowInsetsCompat.Type.systemBars());
|
|
207
|
+
}
|
|
208
|
+
if (bar.isEmpty() || bar.equals(BAR_GESTURE_BAR)) {
|
|
209
|
+
windowInsetsControllerCompat.show(WindowInsetsCompat.Type.navigationBars());
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
private String getStyleForTheme() {
|
|
214
|
+
int currentNightMode = getActivity().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
|
215
|
+
if (currentNightMode != Configuration.UI_MODE_NIGHT_YES) {
|
|
216
|
+
return STYLE_LIGHT;
|
|
217
|
+
}
|
|
218
|
+
return STYLE_DARK;
|
|
219
|
+
}
|
|
220
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capacitor/android",
|
|
3
|
-
"version": "8.0.0-
|
|
3
|
+
"version": "8.0.0-beta.0",
|
|
4
4
|
"description": "Capacitor: Cross-platform apps with JavaScript and the web",
|
|
5
5
|
"homepage": "https://capacitorjs.com",
|
|
6
6
|
"author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"verify": "./gradlew clean lint build test -b capacitor/build.gradle"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@capacitor/core": "^8.0.0-
|
|
26
|
+
"@capacitor/core": "^8.0.0-beta.0"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
|
29
29
|
"access": "public"
|