codeplay-common 4.0.0 ā 4.0.2
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
|
@@ -12,6 +12,13 @@ Donate to get full code including many common functions
|
|
|
12
12
|
https://ko-fi.com/codeplay
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
Version: 4.0.2
|
|
16
|
+
After check & install/download the latest version, the re-check is cancelled now
|
|
17
|
+
|
|
18
|
+
Version: 4.0.1
|
|
19
|
+
Base profile script added
|
|
20
|
+
|
|
21
|
+
|
|
15
22
|
"version": "",
|
|
16
23
|
Version : 4.0.0 (Previous version 3.2.19)
|
|
17
24
|
1) In here we are completly remove the admob-emi and use "capacitor-admob-nextgen"
|
|
@@ -2084,11 +2084,11 @@ if (hasMandatoryUpdate) {
|
|
|
2084
2084
|
process.exit(1);
|
|
2085
2085
|
}
|
|
2086
2086
|
|
|
2087
|
-
console.log('\nš All mandatory plugins auto-updated!
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
return;
|
|
2087
|
+
console.log('\nš All mandatory plugins auto-updated! Skipping recheck for speed.\n');
|
|
2088
|
+
|
|
2089
|
+
saveUpdateLogs();
|
|
2090
|
+
resolve();
|
|
2091
|
+
return;
|
|
2092
2092
|
}
|
|
2093
2093
|
|
|
2094
2094
|
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const rootDir = path.resolve(__dirname, '..');
|
|
5
|
+
const androidDir = path.join(rootDir, 'android');
|
|
6
|
+
const capacitorConfigPath = path.join(rootDir, 'capacitor.config.json');
|
|
7
|
+
const backupProfile = path.join(rootDir, 'baselineProfiles', 'baseline-prof.txt');
|
|
8
|
+
const generatedProfile = path.join(
|
|
9
|
+
androidDir,
|
|
10
|
+
'app',
|
|
11
|
+
'src',
|
|
12
|
+
'main',
|
|
13
|
+
'generated',
|
|
14
|
+
'baselineProfiles',
|
|
15
|
+
'baseline-prof.txt'
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
function readFile(filePath) {
|
|
19
|
+
return fs.readFileSync(filePath, 'utf8');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function writeFile(filePath, content) {
|
|
23
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
24
|
+
fs.writeFileSync(filePath, content);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function patchFile(filePath, patcher) {
|
|
28
|
+
const before = readFile(filePath);
|
|
29
|
+
const after = patcher(before);
|
|
30
|
+
if (after !== before) {
|
|
31
|
+
writeFile(filePath, after);
|
|
32
|
+
console.log(`Updated ${path.relative(rootDir, filePath)}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function insertAfter(content, marker, insertion) {
|
|
37
|
+
if (content.includes(insertion.trim())) return content;
|
|
38
|
+
const index = content.indexOf(marker);
|
|
39
|
+
if (index === -1) return `${content.trimEnd()}\n${insertion}\n`;
|
|
40
|
+
const insertAt = index + marker.length;
|
|
41
|
+
return `${content.slice(0, insertAt)}${insertion}${content.slice(insertAt)}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function insertBeforeClosingBrace(content, blockStart, insertion) {
|
|
45
|
+
if (content.includes(insertion.trim())) return content;
|
|
46
|
+
const startIndex = content.indexOf(blockStart);
|
|
47
|
+
if (startIndex === -1) return content;
|
|
48
|
+
|
|
49
|
+
let depth = 0;
|
|
50
|
+
for (let index = startIndex; index < content.length; index += 1) {
|
|
51
|
+
const char = content[index];
|
|
52
|
+
if (char === '{') depth += 1;
|
|
53
|
+
if (char === '}') {
|
|
54
|
+
depth -= 1;
|
|
55
|
+
if (depth === 0) {
|
|
56
|
+
return `${content.slice(0, index).trimEnd()}\n${insertion}\n${content.slice(index)}`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return content;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getAppIdFromCapacitorConfig() {
|
|
64
|
+
if (!fs.existsSync(capacitorConfigPath)) {
|
|
65
|
+
throw new Error(`capacitor.config.json not found at ${capacitorConfigPath}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let config;
|
|
69
|
+
try {
|
|
70
|
+
config = JSON.parse(readFile(capacitorConfigPath));
|
|
71
|
+
} catch (error) {
|
|
72
|
+
throw new Error(`Failed to parse capacitor.config.json: ${error.message}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const appId = config?.appId;
|
|
76
|
+
if (typeof appId !== 'string' || !appId.trim()) {
|
|
77
|
+
throw new Error('capacitor.config.json does not contain a valid appId.');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return appId.trim();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function sanitizeJavaPackageSegment(segment) {
|
|
84
|
+
const safeSegment = segment.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
85
|
+
return safeSegment.replace(/^[0-9]/, (match) => `_${match}`) || 'app';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function toSafeJavaPackageName(value) {
|
|
89
|
+
return value
|
|
90
|
+
.split('.')
|
|
91
|
+
.map(sanitizeJavaPackageSegment)
|
|
92
|
+
.join('.');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getBaselineProfileBuildGradle(modulePackage) {
|
|
96
|
+
return `apply plugin: 'com.android.test'\napply plugin: 'androidx.baselineprofile'\n\nandroid {\n namespace = \"${modulePackage}\"\n compileSdk = rootProject.ext.compileSdkVersion\n\n defaultConfig {\n minSdkVersion rootProject.ext.minSdkVersion\n targetSdkVersion rootProject.ext.targetSdkVersion\n testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n }\n\n targetProjectPath = \":app\"\n}\n\nbaselineProfile {\n useConnectedDevices true\n}\n\ndependencies {\n implementation \"androidx.benchmark:benchmark-macro-junit4:1.4.0\"\n implementation \"androidx.test.ext:junit:$androidxJunitVersion\"\n implementation \"androidx.test.uiautomator:uiautomator:2.3.0\"\n}\n`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const baselineProfileManifest = `<?xml version="1.0" encoding="utf-8"?>
|
|
100
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
|
|
101
|
+
`;
|
|
102
|
+
|
|
103
|
+
function getBaselineProfileGenerator(modulePackage, appId) {
|
|
104
|
+
return `package ${modulePackage};\n\nimport androidx.benchmark.macro.junit4.BaselineProfileRule;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport kotlin.Unit;\n\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\n@RunWith(AndroidJUnit4.class)\npublic class BaselineProfileGenerator {\n private static final String PACKAGE_NAME = \"${appId}\";\n\n @Rule\n public final BaselineProfileRule baselineProfileRule = new BaselineProfileRule();\n\n @Test\n public void generateStartupProfile() {\n baselineProfileRule.collect(\n PACKAGE_NAME,\n 15,\n 3,\n null,\n true,\n true,\n scope -> {\n scope.getDevice().pressHome();\n scope.startActivityAndWait();\n scope.getDevice().waitForIdle();\n waitForWebViewStartup();\n scope.killProcess();\n return Unit.INSTANCE;\n }\n );\n }\n\n private void waitForWebViewStartup() {\n try {\n Thread.sleep(3000);\n } catch (InterruptedException exception) {\n Thread.currentThread().interrupt();\n }\n }\n}\n`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function ensureBaselineProfilePlugin() {
|
|
108
|
+
const rootBuildGradle = path.join(androidDir, 'build.gradle');
|
|
109
|
+
patchFile(rootBuildGradle, (content) =>
|
|
110
|
+
insertAfter(
|
|
111
|
+
content,
|
|
112
|
+
"classpath 'com.google.gms:google-services:4.4.4'",
|
|
113
|
+
"\n classpath 'androidx.baselineprofile:androidx.baselineprofile.gradle.plugin:1.4.1'"
|
|
114
|
+
)
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function ensureSettingsModule() {
|
|
119
|
+
const settingsGradle = path.join(androidDir, 'settings.gradle');
|
|
120
|
+
patchFile(settingsGradle, (content) =>
|
|
121
|
+
insertAfter(
|
|
122
|
+
content,
|
|
123
|
+
"include ':app'",
|
|
124
|
+
"\ninclude ':baselineprofile'\nproject(':baselineprofile').projectDir = new File('./baselineprofile/')\n"
|
|
125
|
+
)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function ensureAppGradle() {
|
|
130
|
+
const appBuildGradle = path.join(androidDir, 'app', 'build.gradle');
|
|
131
|
+
patchFile(appBuildGradle, (content) => {
|
|
132
|
+
let next = insertAfter(
|
|
133
|
+
content,
|
|
134
|
+
"apply plugin: 'com.android.application'",
|
|
135
|
+
"\napply plugin: 'androidx.baselineprofile'"
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
if (!next.includes('androidx.profileinstaller:profileinstaller')) {
|
|
139
|
+
next = insertBeforeClosingBrace(
|
|
140
|
+
next,
|
|
141
|
+
'dependencies {',
|
|
142
|
+
' implementation "androidx.profileinstaller:profileinstaller:1.4.1"'
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!next.includes("baselineProfile project(':baselineprofile')")) {
|
|
147
|
+
next = insertBeforeClosingBrace(
|
|
148
|
+
next,
|
|
149
|
+
'dependencies {',
|
|
150
|
+
" baselineProfile project(':baselineprofile')"
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!next.includes('automaticGenerationDuringBuild false')) {
|
|
155
|
+
next = insertAfter(
|
|
156
|
+
next,
|
|
157
|
+
"apply from: 'capacitor.build.gradle'",
|
|
158
|
+
'\n\nbaselineProfile {\n automaticGenerationDuringBuild false\n saveInSrc true\n mergeIntoMain true\n}\n'
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return next;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function ensureBaselineProfileModule(appId) {
|
|
167
|
+
const safeAppId = toSafeJavaPackageName(appId);
|
|
168
|
+
const modulePackage = `${safeAppId}.baselineprofile`;
|
|
169
|
+
|
|
170
|
+
writeFile(path.join(androidDir, 'baselineprofile', 'build.gradle'), getBaselineProfileBuildGradle(modulePackage));
|
|
171
|
+
writeFile(
|
|
172
|
+
path.join(androidDir, 'baselineprofile', 'src', 'main', 'AndroidManifest.xml'),
|
|
173
|
+
baselineProfileManifest
|
|
174
|
+
);
|
|
175
|
+
writeFile(
|
|
176
|
+
path.join(
|
|
177
|
+
androidDir,
|
|
178
|
+
'baselineprofile',
|
|
179
|
+
'src',
|
|
180
|
+
'main',
|
|
181
|
+
'java',
|
|
182
|
+
...safeAppId.split('.'),
|
|
183
|
+
'baselineprofile',
|
|
184
|
+
'BaselineProfileGenerator.java'
|
|
185
|
+
),
|
|
186
|
+
getBaselineProfileGenerator(modulePackage, appId)
|
|
187
|
+
);
|
|
188
|
+
console.log('Ensured android/baselineprofile module');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function syncGeneratedProfileBackup() {
|
|
192
|
+
const generatedExists = fs.existsSync(generatedProfile);
|
|
193
|
+
const backupExists = fs.existsSync(backupProfile);
|
|
194
|
+
|
|
195
|
+
if (!generatedExists && !backupExists) {
|
|
196
|
+
console.log('No baseline-prof.txt found yet. Run: cd android && .\\gradlew.bat :app:generateBaselineProfile --console=plain');
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (generatedExists && !backupExists) {
|
|
201
|
+
fs.mkdirSync(path.dirname(backupProfile), { recursive: true });
|
|
202
|
+
fs.copyFileSync(generatedProfile, backupProfile);
|
|
203
|
+
console.log('Backed up generated baseline profile to baselineProfiles/baseline-prof.txt');
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (!generatedExists && backupExists) {
|
|
208
|
+
fs.mkdirSync(path.dirname(generatedProfile), { recursive: true });
|
|
209
|
+
fs.copyFileSync(backupProfile, generatedProfile);
|
|
210
|
+
console.log('Restored baseline profile into android/app/src/main/generated/baselineProfiles');
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const generatedTime = fs.statSync(generatedProfile).mtimeMs;
|
|
215
|
+
const backupTime = fs.statSync(backupProfile).mtimeMs;
|
|
216
|
+
if (generatedTime >= backupTime) {
|
|
217
|
+
fs.copyFileSync(generatedProfile, backupProfile);
|
|
218
|
+
console.log('Updated baseline profile backup from generated profile');
|
|
219
|
+
} else {
|
|
220
|
+
fs.copyFileSync(backupProfile, generatedProfile);
|
|
221
|
+
console.log('Restored generated baseline profile from backup');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function main() {
|
|
226
|
+
const appId = getAppIdFromCapacitorConfig();
|
|
227
|
+
|
|
228
|
+
if (!fs.existsSync(androidDir)) {
|
|
229
|
+
console.log('Android platform folder is missing. Run `npx cap add android` first, then rerun this script.');
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
ensureBaselineProfilePlugin();
|
|
234
|
+
ensureSettingsModule();
|
|
235
|
+
ensureAppGradle();
|
|
236
|
+
ensureBaselineProfileModule(appId);
|
|
237
|
+
syncGeneratedProfileBackup();
|
|
238
|
+
console.log('Baseline Profile setup is ready.');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
main();
|
package/package.json
CHANGED
package/scripts/sync-files.js
CHANGED
|
@@ -54,6 +54,15 @@ const latestSplashAnimation = getLatestFile("setSplashAnimation-");
|
|
|
54
54
|
const latestCodeplayBuild = getLatestFile("codeplayBeforeBuild-");
|
|
55
55
|
|
|
56
56
|
const latestPackageIdModification = getLatestFile("packageidBaseModification-");
|
|
57
|
+
const baselineProfileSetupScript = "node scripts/setup-baseline-profile.js";
|
|
58
|
+
const baselineProfileGenerateScript = "cd android && gradlew.bat :app:generateBaselineProfile --console=plain";
|
|
59
|
+
|
|
60
|
+
function appendIfMissing(base, suffix) {
|
|
61
|
+
if (!suffix) return base;
|
|
62
|
+
if (!base || typeof base !== "string") return suffix;
|
|
63
|
+
if (base.includes(suffix)) return base;
|
|
64
|
+
return `${base} && ${suffix}`;
|
|
65
|
+
}
|
|
57
66
|
|
|
58
67
|
|
|
59
68
|
// Update package.json
|
|
@@ -67,9 +76,19 @@ if (latestCodeplayBuild) {
|
|
|
67
76
|
packageJson.scripts["build"] = `node buildCodeplay/${latestCodeplayBuild} && node buildCodeplay/${latestPackageIdModification} && cross-env NODE_ENV=production vite build --logLevel warn`;
|
|
68
77
|
}
|
|
69
78
|
if (latestSplashScreen && latestSplashAnimation) {
|
|
70
|
-
packageJson.scripts["capacitor:sync:after"] =
|
|
79
|
+
packageJson.scripts["capacitor:sync:after"] = appendIfMissing(
|
|
80
|
+
`node buildCodeplay/${latestSplashScreen} && node buildCodeplay/${latestSplashAnimation} && node buildCodeplay/manifestModification.js`,
|
|
81
|
+
baselineProfileSetupScript
|
|
82
|
+
);
|
|
71
83
|
//node buildCodeplay/ios-emi-admob-modification.js &&
|
|
84
|
+
} else if (packageJson.scripts["capacitor:sync:after"]) {
|
|
85
|
+
packageJson.scripts["capacitor:sync:after"] = appendIfMissing(
|
|
86
|
+
packageJson.scripts["capacitor:sync:after"],
|
|
87
|
+
baselineProfileSetupScript
|
|
88
|
+
);
|
|
72
89
|
}
|
|
90
|
+
packageJson.scripts["baseline-profile:setup"] = baselineProfileSetupScript;
|
|
91
|
+
packageJson.scripts["baseline-profile:generate"] = baselineProfileGenerateScript;
|
|
73
92
|
|
|
74
93
|
packageJson.scripts["ionic:build"] = "npm run build";
|
|
75
94
|
packageJson.scripts["ionic:serve"] = "npm run start";
|
package/scripts/uninstall.js
CHANGED
|
@@ -12,6 +12,8 @@ const path = require("path");
|
|
|
12
12
|
const projectRoot = path.resolve(__dirname, "../../../"); // Project root
|
|
13
13
|
const commonBuildPath = path.join(__dirname, "../files"); // Path where files were copied from
|
|
14
14
|
const splashXmlPath = path.join(projectRoot, "buildCodeplay"); // Path to splashxml folder
|
|
15
|
+
const baselineProfileSetupScript = path.join(projectRoot, "scripts", "setup-baseline-profile.js");
|
|
16
|
+
const baselineProfileBackup = path.join(projectRoot, "baselineProfiles", "baseline-prof.txt");
|
|
15
17
|
|
|
16
18
|
process.stdout.write("š Uninstalling: Removing old and copied files...\n");
|
|
17
19
|
|
|
@@ -59,14 +61,21 @@ filesInProject.forEach(file => {
|
|
|
59
61
|
}
|
|
60
62
|
});
|
|
61
63
|
|
|
62
|
-
// Remove files listed in commonBuildPath
|
|
64
|
+
// Remove files and folders listed in commonBuildPath
|
|
63
65
|
if (fs.existsSync(commonBuildPath)) {
|
|
64
66
|
fs.readdirSync(commonBuildPath).forEach(file => {
|
|
65
67
|
const destPath = path.join(projectRoot, file);
|
|
68
|
+
if (file === "scripts") {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
66
71
|
if (fs.existsSync(destPath)) {
|
|
67
72
|
try {
|
|
68
|
-
fs.
|
|
69
|
-
|
|
73
|
+
if (fs.lstatSync(destPath).isDirectory()) {
|
|
74
|
+
removeDirectory(destPath);
|
|
75
|
+
} else {
|
|
76
|
+
fs.unlinkSync(destPath);
|
|
77
|
+
process.stdout.write(`šļø Removed file: ${destPath}\n`);
|
|
78
|
+
}
|
|
70
79
|
} catch (error) {
|
|
71
80
|
process.stderr.write(`ā ļø Failed to remove ${destPath}: ${error.message}\n`);
|
|
72
81
|
}
|
|
@@ -74,4 +83,22 @@ if (fs.existsSync(commonBuildPath)) {
|
|
|
74
83
|
});
|
|
75
84
|
}
|
|
76
85
|
|
|
86
|
+
if (fs.existsSync(baselineProfileSetupScript)) {
|
|
87
|
+
try {
|
|
88
|
+
fs.unlinkSync(baselineProfileSetupScript);
|
|
89
|
+
process.stdout.write(`šļø Removed file: ${baselineProfileSetupScript}\n`);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
process.stderr.write(`ā ļø Failed to remove ${baselineProfileSetupScript}: ${error.message}\n`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (fs.existsSync(baselineProfileBackup)) {
|
|
96
|
+
try {
|
|
97
|
+
fs.unlinkSync(baselineProfileBackup);
|
|
98
|
+
process.stdout.write(`šļø Removed file: ${baselineProfileBackup}\n`);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
process.stderr.write(`ā ļø Failed to remove ${baselineProfileBackup}: ${error.message}\n`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
77
104
|
process.stdout.write("ā
Uninstall cleanup complete!\n");
|