@capacitor/cli 9.0.0-alpha.6 → 9.0.0-alpha.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/assets/android-template.tar.gz +0 -0
- package/assets/capacitor-cordova-android-plugins.tar.gz +0 -0
- package/assets/capacitor-cordova-ios-plugins.tar.gz +0 -0
- package/assets/ios-pods-template.tar.gz +0 -0
- package/assets/ios-spm-template.tar.gz +0 -0
- package/dist/android/update.js +6 -3
- package/dist/config.js +5 -3
- package/dist/cordova.js +16 -3
- package/dist/declarations.d.ts +70 -4
- package/dist/ios/update.js +21 -7
- package/dist/tasks/migrate-edge-to-edge.js +158 -0
- package/dist/tasks/migrate-swiftui.js +335 -0
- package/dist/tasks/migrate.js +158 -32
- package/dist/util/capacitor-package.js +297 -0
- package/dist/util/cordova-ios.js +144 -12
- package/dist/util/node.js +35 -1
- package/dist/util/spm.js +82 -11
- package/dist/util/xcode.js +48 -0
- package/package.json +4 -2
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/android/update.js
CHANGED
|
@@ -24,11 +24,14 @@ async function updateAndroid(config) {
|
|
|
24
24
|
const capacitorPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
|
|
25
25
|
(0, plugin_1.printPlugins)(capacitorPlugins, 'android');
|
|
26
26
|
const cordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
|
|
27
|
-
const enableCordova = cordovaPlugins.length > 0;
|
|
27
|
+
const enableCordova = cordovaPlugins.length > 0 || config.app.forceCordova;
|
|
28
28
|
await writePluginsJson(config, capacitorPlugins, enableCordova);
|
|
29
29
|
await removePluginsNativeFiles(config);
|
|
30
30
|
if (enableCordova) {
|
|
31
31
|
log_1.logger.info('Found Cordova Plugins: Including Android Cordova Support');
|
|
32
|
+
if (config.app.forceCordova) {
|
|
33
|
+
log_1.logger.info('Cordova support installation has been forced');
|
|
34
|
+
}
|
|
32
35
|
await copyPluginsNativeFiles(config, cordovaPlugins);
|
|
33
36
|
}
|
|
34
37
|
if (!(await (0, fs_extra_1.pathExists)(config.android.webDirAbs))) {
|
|
@@ -75,7 +78,7 @@ async function findAndroidPluginClassesInPlugin(plugin) {
|
|
|
75
78
|
const srcFiles = await (0, fs_1.readdirp)(srcPath, {
|
|
76
79
|
filter: (entry) => !entry.stats.isDirectory() && ['.java', '.kt'].includes((0, path_1.extname)(entry.path)),
|
|
77
80
|
});
|
|
78
|
-
const classRegex = /^@
|
|
81
|
+
const classRegex = /^@CapacitorPlugin[\s\S]+?class ([\w]+)/gm;
|
|
79
82
|
const packageRegex = /^package ([\w.]+);?$/gm;
|
|
80
83
|
debug('Searching %O source files in %O by %O regex', srcFiles.length, srcPath, classRegex);
|
|
81
84
|
const entries = await Promise.all(srcFiles.map(async (srcFile) => {
|
|
@@ -107,7 +110,7 @@ async function installGradlePlugins(config, capacitorPlugins, cordovaPlugins) {
|
|
|
107
110
|
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong('node_modules/@capacitor/android')}.\n` +
|
|
108
111
|
`Are you sure ${colors_1.default.strong('@capacitor/android')} is installed?`);
|
|
109
112
|
}
|
|
110
|
-
const enableCordova = cordovaPlugins.length > 0;
|
|
113
|
+
const enableCordova = cordovaPlugins.length > 0 || config.app.forceCordova;
|
|
111
114
|
const capacitorAndroidPath = (0, path_1.resolve)((0, path_1.dirname)(capacitorAndroidPackagePath), 'capacitor');
|
|
112
115
|
const capacitorCordovaAndroidPath = (0, path_1.resolve)((0, path_1.dirname)(capacitorAndroidPackagePath), 'capacitor-cordova');
|
|
113
116
|
const settingsPath = config.android.platformDirAbs;
|
package/dist/config.js
CHANGED
|
@@ -20,7 +20,7 @@ exports.CONFIG_FILE_NAME_TS = 'capacitor.config.ts';
|
|
|
20
20
|
exports.CONFIG_FILE_NAME_JS = 'capacitor.config.js';
|
|
21
21
|
exports.CONFIG_FILE_NAME_JSON = 'capacitor.config.json';
|
|
22
22
|
async function loadConfig() {
|
|
23
|
-
var _a, _b, _c, _d;
|
|
23
|
+
var _a, _b, _c, _d, _e;
|
|
24
24
|
const appRootDir = process.cwd();
|
|
25
25
|
const cliRootDir = (0, path_1.dirname)(__dirname);
|
|
26
26
|
const conf = await loadExtConfig(appRootDir);
|
|
@@ -41,6 +41,7 @@ async function loadConfig() {
|
|
|
41
41
|
const appId = (_a = conf.extConfig.appId) !== null && _a !== void 0 ? _a : '';
|
|
42
42
|
const appName = (_b = conf.extConfig.appName) !== null && _b !== void 0 ? _b : '';
|
|
43
43
|
const webDir = (_c = conf.extConfig.webDir) !== null && _c !== void 0 ? _c : 'www';
|
|
44
|
+
const forceCordova = (_d = conf.extConfig.forceCordovaInclusion) !== null && _d !== void 0 ? _d : false;
|
|
44
45
|
const cli = await loadCLIConfig(cliRootDir);
|
|
45
46
|
const config = {
|
|
46
47
|
android: await loadAndroidConfig(appRootDir, conf.extConfig, cli),
|
|
@@ -53,7 +54,8 @@ async function loadConfig() {
|
|
|
53
54
|
appName,
|
|
54
55
|
webDir,
|
|
55
56
|
webDirAbs: (0, path_1.resolve)(appRootDir, webDir),
|
|
56
|
-
|
|
57
|
+
forceCordova,
|
|
58
|
+
package: (_e = (await (0, fn_1.tryFn)(fs_extra_1.readJSON, (0, path_1.resolve)(appRootDir, 'package.json')))) !== null && _e !== void 0 ? _e : {
|
|
57
59
|
name: appName,
|
|
58
60
|
version: '1.0.0',
|
|
59
61
|
...depsForNx,
|
|
@@ -87,7 +89,7 @@ async function loadExtConfigTS(rootDir, extConfigName, extConfigFilePath) {
|
|
|
87
89
|
`To use ${colors_1.default.strong(extConfigName)} files, you must install TypeScript in your project, e.g. w/ ${colors_1.default.input('npm install -D typescript')}`);
|
|
88
90
|
}
|
|
89
91
|
const ts = require(tsPath); // eslint-disable-line @typescript-eslint/no-var-requires
|
|
90
|
-
const extConfigObject = (0, node_1.requireTS)(ts, extConfigFilePath);
|
|
92
|
+
const extConfigObject = (await (0, node_1.requireTS)(ts, extConfigFilePath));
|
|
91
93
|
const extConfig = extConfigObject.default ? await extConfigObject.default : extConfigObject;
|
|
92
94
|
return {
|
|
93
95
|
extConfigType: 'ts',
|
package/dist/cordova.js
CHANGED
|
@@ -754,13 +754,26 @@ async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cle
|
|
|
754
754
|
});
|
|
755
755
|
});
|
|
756
756
|
const cleartextString = 'android:usesCleartextTraffic="true"';
|
|
757
|
-
const
|
|
758
|
-
?
|
|
757
|
+
const networkSecurityConfigValue = cleartext || ((_a = config.app.extConfig.server) === null || _a === void 0 ? void 0 : _a.cleartext) || applicationXMLAttributes.includes(cleartextString)
|
|
758
|
+
? 'android:networkSecurityConfig="@xml/network_security_config"'
|
|
759
759
|
: '';
|
|
760
|
+
const networkSecurityConfigDir = (0, path_1.join)(config.android.cordovaPluginsDirAbs, 'src', 'main', 'res', 'xml');
|
|
761
|
+
const networkSecurityConfigPath = (0, path_1.join)(networkSecurityConfigDir, 'network_security_config.xml');
|
|
762
|
+
if (networkSecurityConfigValue) {
|
|
763
|
+
await (0, fs_extra_1.ensureDir)(networkSecurityConfigDir);
|
|
764
|
+
await (0, fs_extra_1.writeFile)(networkSecurityConfigPath, `<?xml version="1.0" encoding="utf-8"?>
|
|
765
|
+
<network-security-config>
|
|
766
|
+
<base-config cleartextTrafficPermitted="true" />
|
|
767
|
+
</network-security-config>
|
|
768
|
+
`);
|
|
769
|
+
}
|
|
770
|
+
else if (await (0, fs_extra_1.pathExists)(networkSecurityConfigPath)) {
|
|
771
|
+
await (0, fs_extra_1.remove)(networkSecurityConfigPath);
|
|
772
|
+
}
|
|
760
773
|
let content = `<?xml version='1.0' encoding='utf-8'?>
|
|
761
774
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
762
775
|
xmlns:amazon="http://schemas.amazon.com/apk/res/android">
|
|
763
|
-
<application ${applicationXMLAttributes.join('\n')} ${
|
|
776
|
+
<application ${applicationXMLAttributes.filter((attr) => !attr.includes('android:usesCleartextTraffic')).join('\n')} ${networkSecurityConfigValue}>
|
|
764
777
|
${applicationXMLEntries.join('\n')}
|
|
765
778
|
</application>
|
|
766
779
|
${rootXMLEntries.join('\n')}
|
package/dist/declarations.d.ts
CHANGED
|
@@ -76,6 +76,14 @@ export interface CapacitorConfig {
|
|
|
76
76
|
* @default true
|
|
77
77
|
*/
|
|
78
78
|
initialFocus?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* If set, will include Cordova support libraries regardless
|
|
81
|
+
* of whether or not they are needed by plugins.
|
|
82
|
+
*
|
|
83
|
+
* @since 9.0.0
|
|
84
|
+
* @default false
|
|
85
|
+
*/
|
|
86
|
+
forceCordovaInclusion?: boolean;
|
|
79
87
|
android?: {
|
|
80
88
|
/**
|
|
81
89
|
* Specify a custom path to the native Android project.
|
|
@@ -520,6 +528,46 @@ export interface CapacitorConfig {
|
|
|
520
528
|
packageOptions?: {
|
|
521
529
|
[pluginId: string]: PackageOptions;
|
|
522
530
|
};
|
|
531
|
+
/**
|
|
532
|
+
* Override which Capacitor Swift package the generated `Package.swift` depends on.
|
|
533
|
+
*
|
|
534
|
+
* By default the generated package pins the git tag matching the installed
|
|
535
|
+
* `@capacitor/ios` version, which is correct for both stable and pre-release versions
|
|
536
|
+
* and matches what CocoaPods resolves.
|
|
537
|
+
*
|
|
538
|
+
* Set this only when developing against an unreleased Capacitor, such as a local
|
|
539
|
+
* checkout or a feature branch. Exactly one of `path`, `branch`, `revision`, `exact`,
|
|
540
|
+
* or `from` must be set. `path` points at the repository root (the directory containing
|
|
541
|
+
* `Package.swift`) and may be relative to the app.
|
|
542
|
+
*
|
|
543
|
+
* The `CAPACITOR_IOS_PACKAGE` environment variable takes precedence over this setting,
|
|
544
|
+
* so a checkout can be redirected without editing committed configuration.
|
|
545
|
+
*
|
|
546
|
+
* Note that `branch` and `revision` builds are not reproducible and decouple the native
|
|
547
|
+
* code from the `@capacitor/core` JavaScript bridge it is versioned against.
|
|
548
|
+
*
|
|
549
|
+
* @since 9.0.0
|
|
550
|
+
* @example { "path": "../capacitor" }
|
|
551
|
+
* @example { "branch": "next" }
|
|
552
|
+
*/
|
|
553
|
+
capacitorPackage?: {
|
|
554
|
+
/**
|
|
555
|
+
* Repository to fetch from. Ignored when `path` is set.
|
|
556
|
+
*
|
|
557
|
+
* @default 'https://github.com/ionic-team/capacitor'
|
|
558
|
+
*/
|
|
559
|
+
url?: string;
|
|
560
|
+
/** Path to a local Capacitor repository root. */
|
|
561
|
+
path?: string;
|
|
562
|
+
/** Branch to track. */
|
|
563
|
+
branch?: string;
|
|
564
|
+
/** Exact commit to pin. */
|
|
565
|
+
revision?: string;
|
|
566
|
+
/** Exact version tag to pin. */
|
|
567
|
+
exact?: string;
|
|
568
|
+
/** Minimum version tag, allowing compatible upgrades. */
|
|
569
|
+
from?: string;
|
|
570
|
+
};
|
|
523
571
|
};
|
|
524
572
|
};
|
|
525
573
|
};
|
|
@@ -709,13 +757,31 @@ export interface PluginsConfig {
|
|
|
709
757
|
*
|
|
710
758
|
* This option is only supported on Android.
|
|
711
759
|
*
|
|
712
|
-
* `
|
|
760
|
+
* `native` = (recommended) For older Chromium versions (< v140) this embeds the webview with padding and sets the `env(safe-area-inset-*)` variables to `0px`. For newer Chromium versions (>= v140) this makes sure the webview adheres to the `viewport-fit` meta tag. If set to `viewport-fit="cover"` this will make the webview edge-to-edge and the `env(safe-area-inset-*)` variables will contain the correct values. With those values you could set padding for example so make sure the webview is shown correctly.
|
|
761
|
+
*
|
|
762
|
+
* `css` = This is the same as `native`, but it also injects CSS variables (`--safe-area-inset-*`) containing correct safe area inset values into the webview.
|
|
763
|
+
*
|
|
764
|
+
* `disable` = (not recommended) Disable safe area insets handling completely.
|
|
765
|
+
* This shifts the responsibility from Capacitor to your own code to handle the insets.
|
|
766
|
+
* Be aware that this might result in a visually broken UI if your native app code and the content loaded into the webview do not correctly handle safe area insets.
|
|
713
767
|
*
|
|
714
|
-
*
|
|
768
|
+
* @default "native"
|
|
769
|
+
*/
|
|
770
|
+
insetsHandling?: 'native' | 'css' | 'disable';
|
|
771
|
+
/**
|
|
772
|
+
* Set an initial value for the to be detected `viewport-fit=` meta tag value.
|
|
773
|
+
* For most apps that support edge-to-edge this value will eventually be `cover`.
|
|
774
|
+
* Therefore you might want to set this value to `cover` to help prevent layout jumps and glitches.
|
|
775
|
+
* If you know the value to be `cover` initially, you can set it here.
|
|
776
|
+
* The value will always end up correctly, no matter what you set here,
|
|
777
|
+
* as long as `insetsHandling` is set to `native` or `css`.
|
|
778
|
+
* It only exists to help prevent layout jumps and glitches.
|
|
779
|
+
*
|
|
780
|
+
* This option is only supported on Android.
|
|
715
781
|
*
|
|
716
|
-
* @default
|
|
782
|
+
* @default undefined
|
|
717
783
|
*/
|
|
718
|
-
|
|
784
|
+
initialViewportFitValueHint?: 'auto' | 'contain' | 'cover';
|
|
719
785
|
/**
|
|
720
786
|
* The style of the text and icons of the system bars.
|
|
721
787
|
*
|
package/dist/ios/update.js
CHANGED
|
@@ -13,6 +13,7 @@ const log_1 = require("../log");
|
|
|
13
13
|
const plugin_1 = require("../plugin");
|
|
14
14
|
const copy_1 = require("../tasks/copy");
|
|
15
15
|
const migrate_1 = require("../tasks/migrate");
|
|
16
|
+
const capacitor_package_1 = require("../util/capacitor-package");
|
|
16
17
|
const cordova_ios_1 = require("../util/cordova-ios");
|
|
17
18
|
const fs_1 = require("../util/fs");
|
|
18
19
|
const iosplugin_1 = require("../util/iosplugin");
|
|
@@ -34,9 +35,12 @@ async function updatePluginFiles(config, plugins, deployment) {
|
|
|
34
35
|
var _a;
|
|
35
36
|
await (0, cordova_ios_1.removePluginsNativeFiles)(config);
|
|
36
37
|
const cordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
|
|
37
|
-
const enableCordova = cordovaPlugins.length > 0;
|
|
38
|
+
const enableCordova = cordovaPlugins.length > 0 || config.app.forceCordova;
|
|
38
39
|
if (enableCordova) {
|
|
39
40
|
log_1.logger.info('Found Cordova Plugins: Including iOS Cordova Support');
|
|
41
|
+
if (config.app.forceCordova) {
|
|
42
|
+
log_1.logger.info('Cordova support installation has been forced');
|
|
43
|
+
}
|
|
40
44
|
await (0, cordova_ios_1.copyPluginsNativeFiles)(config, cordovaPlugins);
|
|
41
45
|
}
|
|
42
46
|
if (!(await (0, fs_extra_1.pathExists)(await config.ios.webDirAbs))) {
|
|
@@ -49,20 +53,30 @@ async function updatePluginFiles(config, plugins, deployment) {
|
|
|
49
53
|
await (0, cordova_ios_1.generateCordovaPackageFiles)(cordovaPlugins, config);
|
|
50
54
|
}
|
|
51
55
|
const validSPMPackages = await (0, spm_1.checkPluginsForPackageSwift)(config, plugins);
|
|
56
|
+
const iosPlatformVersion = await (0, common_1.getCapacitorPackageVersion)(config, config.ios.name);
|
|
57
|
+
const majorCapVersion = (0, semver_1.major)(iosPlatformVersion);
|
|
58
|
+
const capacitorPackage = await (0, capacitor_package_1.resolveCapacitorPackage)(config, 'from');
|
|
52
59
|
await Promise.all(validSPMPackages.map(async (plugin) => {
|
|
53
|
-
var _a;
|
|
54
|
-
const iosPlatformVersion = await (0, common_1.getCapacitorPackageVersion)(config, config.ios.name);
|
|
55
60
|
const packageSwiftPath = (0, path_1.join)(plugin.rootPath, 'Package.swift');
|
|
56
61
|
let content = await (0, fs_extra_1.readFile)(packageSwiftPath, { encoding: 'utf-8' });
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
const version = (0, capacitor_package_1.findCapacitorDependencyVersion)(content);
|
|
63
|
+
if (version && (0, semver_1.major)(version) != majorCapVersion) {
|
|
64
|
+
log_1.logger.warn(`${plugin.id} is built for Capacitor ${(0, semver_1.major)(version)}, it might cause issues`);
|
|
65
|
+
}
|
|
66
|
+
if (capacitorPackage.sourceBased) {
|
|
67
|
+
// The plugin has to resolve to the same package identity as the app, or SPM ends up with
|
|
68
|
+
// two packages that both vend a Capacitor product.
|
|
69
|
+
const rewritten = (0, capacitor_package_1.rewriteCapacitorDependency)(content, capacitorPackage, plugin.rootPath);
|
|
70
|
+
if (rewritten !== content) {
|
|
71
|
+
await (0, fs_extra_1.writeFile)(packageSwiftPath, rewritten);
|
|
72
|
+
}
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
60
75
|
if (version && (0, semver_1.major)(version) != majorCapVersion) {
|
|
61
76
|
const preCapVersion = (0, semver_1.prerelease)(iosPlatformVersion);
|
|
62
77
|
const forceVersion = preCapVersion ? iosPlatformVersion : `${majorCapVersion}.0.0`;
|
|
63
78
|
content = (0, migrate_1.setAllStringIn)(content, `url: "https://github.com/ionic-team/capacitor-swift-pm.git",`, `)`, ` from: "${forceVersion}"`);
|
|
64
79
|
await (0, fs_extra_1.writeFile)(packageSwiftPath, content);
|
|
65
|
-
log_1.logger.warn(`${plugin.id} is built for Capacitor ${(0, semver_1.major)(version)}, it might cause issues`);
|
|
66
80
|
}
|
|
67
81
|
}));
|
|
68
82
|
await (0, spm_1.generatePackageFile)(config, validSPMPackages.concat(cordovaPlugins));
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.__testables = exports.migrateToEdgeToEdge = void 0;
|
|
4
|
+
const fs_extra_1 = require("fs-extra");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const log_1 = require("../log");
|
|
7
|
+
const fs_1 = require("../util/fs");
|
|
8
|
+
const JAVA = {
|
|
9
|
+
imports: ['import android.os.Bundle;', 'import androidx.activity.EdgeToEdge;'],
|
|
10
|
+
enableCall: 'EdgeToEdge.enable(this);',
|
|
11
|
+
onCreate: `
|
|
12
|
+
@Override
|
|
13
|
+
protected void onCreate(Bundle savedInstanceState) {
|
|
14
|
+
super.onCreate(savedInstanceState);
|
|
15
|
+
EdgeToEdge.enable(this);
|
|
16
|
+
}
|
|
17
|
+
`,
|
|
18
|
+
};
|
|
19
|
+
const KOTLIN = {
|
|
20
|
+
imports: ['import android.os.Bundle', 'import androidx.activity.enableEdgeToEdge'],
|
|
21
|
+
enableCall: 'enableEdgeToEdge()',
|
|
22
|
+
onCreate: `
|
|
23
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
24
|
+
super.onCreate(savedInstanceState)
|
|
25
|
+
enableEdgeToEdge()
|
|
26
|
+
}
|
|
27
|
+
`,
|
|
28
|
+
};
|
|
29
|
+
async function migrateToEdgeToEdge(config) {
|
|
30
|
+
var _a, _b;
|
|
31
|
+
if (((_b = (_a = config.app.extConfig.plugins) === null || _a === void 0 ? void 0 : _a.SystemBars) === null || _b === void 0 ? void 0 : _b.insetsHandling) === 'disable') {
|
|
32
|
+
log_1.logger.info(`Edge-to-edge migration: SystemBars insetsHandling is 'disable', skipping.`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const activities = await findBridgeActivities(config);
|
|
36
|
+
if (activities.length === 0) {
|
|
37
|
+
log_1.logger.warn(`Edge-to-edge migration: no Activity extending BridgeActivity found. ${manualInstructions(JAVA.enableCall)}`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (activities.length > 1) {
|
|
41
|
+
log_1.logger.warn(`Edge-to-edge migration: found more than one Activity extending BridgeActivity (${activities.join(', ')}), ` +
|
|
42
|
+
`skipping. ${manualInstructions(JAVA.enableCall)}`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const path = activities[0];
|
|
46
|
+
const language = path.endsWith('.kt') ? KOTLIN : JAVA;
|
|
47
|
+
const source = (0, fs_extra_1.readFileSync)(path, 'utf-8');
|
|
48
|
+
if (hasEdgeToEdgeEnabled(source)) {
|
|
49
|
+
log_1.logger.info('Edge-to-edge migration: Activity already enables edge-to-edge, skipping.');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const patched = patchActivitySource(source, language);
|
|
53
|
+
if (!patched) {
|
|
54
|
+
log_1.logger.warn(`Edge-to-edge migration: could not patch ${path}. ${manualInstructions(language.enableCall)}`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
(0, fs_extra_1.writeFileSync)(path, patched, 'utf-8');
|
|
58
|
+
}
|
|
59
|
+
exports.migrateToEdgeToEdge = migrateToEdgeToEdge;
|
|
60
|
+
function manualInstructions(enableCall) {
|
|
61
|
+
return (`Add ${enableCall} to the onCreate of the Activity hosting Capacitor. ` +
|
|
62
|
+
`Without it the 'native' insetsHandling default of the SystemBars plugin cannot apply safe area insets.`);
|
|
63
|
+
}
|
|
64
|
+
async function findBridgeActivities(config) {
|
|
65
|
+
const javaDir = (0, path_1.join)(config.android.srcMainDirAbs, 'java');
|
|
66
|
+
if (!(0, fs_extra_1.existsSync)(javaDir)) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
const sources = await (0, fs_1.readdirp)(javaDir, {
|
|
70
|
+
filter: (entry) => !entry.stats.isDirectory() && (entry.path.endsWith('.java') || entry.path.endsWith('.kt')),
|
|
71
|
+
});
|
|
72
|
+
return sources.filter((path) => (0, fs_extra_1.readFileSync)(path, 'utf-8').includes('BridgeActivity'));
|
|
73
|
+
}
|
|
74
|
+
function hasEdgeToEdgeEnabled(source) {
|
|
75
|
+
return source.includes('EdgeToEdge.enable(') || source.includes('enableEdgeToEdge(');
|
|
76
|
+
}
|
|
77
|
+
function patchActivitySource(source, language) {
|
|
78
|
+
var _a;
|
|
79
|
+
const patched = (_a = insertEnableCall(source, language)) !== null && _a !== void 0 ? _a : insertOnCreate(source, language);
|
|
80
|
+
if (!patched) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
return addImports(patched, language.imports);
|
|
84
|
+
}
|
|
85
|
+
function insertEnableCall(source, language) {
|
|
86
|
+
var _a, _b;
|
|
87
|
+
const lines = source.split('\n');
|
|
88
|
+
const superCall = lines.findIndex((line) => line.includes('super.onCreate('));
|
|
89
|
+
if (superCall === -1) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
const indentation = (_b = (_a = lines[superCall].match(/^\s*/)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : '';
|
|
93
|
+
lines.splice(superCall + 1, 0, `${indentation}${language.enableCall}`);
|
|
94
|
+
return lines.join('\n');
|
|
95
|
+
}
|
|
96
|
+
function insertOnCreate(source, language) {
|
|
97
|
+
const classDeclaration = source.search(/\bclass\s+\w+/);
|
|
98
|
+
if (classDeclaration === -1) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
const bodyStart = source.indexOf('{', classDeclaration);
|
|
102
|
+
if (bodyStart === -1) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const bodyEnd = findMatchingBrace(source, bodyStart);
|
|
106
|
+
if (bodyEnd === -1) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
const body = source.slice(0, bodyEnd).replace(/\s*$/, '\n');
|
|
110
|
+
return body + language.onCreate + source.slice(bodyEnd);
|
|
111
|
+
}
|
|
112
|
+
function findMatchingBrace(source, openIndex) {
|
|
113
|
+
let depth = 0;
|
|
114
|
+
for (let i = openIndex; i < source.length; i++) {
|
|
115
|
+
if (source[i] === '{') {
|
|
116
|
+
depth++;
|
|
117
|
+
}
|
|
118
|
+
else if (source[i] === '}') {
|
|
119
|
+
depth--;
|
|
120
|
+
if (depth === 0) {
|
|
121
|
+
return i;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return -1;
|
|
126
|
+
}
|
|
127
|
+
function addImports(source, statements) {
|
|
128
|
+
const lines = source.split('\n');
|
|
129
|
+
for (const statement of statements) {
|
|
130
|
+
if (!lines.includes(statement)) {
|
|
131
|
+
lines.splice(importInsertIndex(lines, statement), 0, statement);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return lines.join('\n');
|
|
135
|
+
}
|
|
136
|
+
function importInsertIndex(lines, statement) {
|
|
137
|
+
const sortsAfter = lines.findIndex((line) => line.startsWith('import ') && line > statement);
|
|
138
|
+
if (sortsAfter !== -1) {
|
|
139
|
+
return sortsAfter;
|
|
140
|
+
}
|
|
141
|
+
let lastImport = -1;
|
|
142
|
+
lines.forEach((line, index) => {
|
|
143
|
+
if (line.startsWith('import ')) {
|
|
144
|
+
lastImport = index;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
if (lastImport !== -1) {
|
|
148
|
+
return lastImport + 1;
|
|
149
|
+
}
|
|
150
|
+
return lines.findIndex((line) => line.startsWith('package ')) + 1;
|
|
151
|
+
}
|
|
152
|
+
exports.__testables = {
|
|
153
|
+
JAVA,
|
|
154
|
+
KOTLIN,
|
|
155
|
+
addImports,
|
|
156
|
+
hasEdgeToEdgeEnabled,
|
|
157
|
+
patchActivitySource,
|
|
158
|
+
};
|