codeplay-common 4.9.9 → 4.10.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/CHANGELOG.md +16 -0
- package/README.md +24 -10
- package/RELEASE_NOTES.md +16 -0
- package/files/buildCodeplay/{add-splash-screen-1.6.js → add-splash-screen.js} +255 -254
- package/files/buildCodeplay/apk-store-builder.js +97 -97
- package/files/buildCodeplay/{codeplayBeforeBuild-6.5.js → codeplayBeforeBuild.js} +160 -80
- package/files/buildCodeplay/fix-onesignal-plugin.js +96 -96
- package/files/buildCodeplay/ios-emi-admob-modification.js +24 -24
- package/files/buildCodeplay/manifestModification.js +23 -23
- package/files/buildCodeplay/{packageidBaseModification-1.4.js → packageidBaseModification.js} +445 -445
- package/files/buildCodeplay/project-scripts.cjs +56 -0
- package/files/buildCodeplay/{setSplashAnimation-1.4.js → setSplashAnimation.js} +156 -156
- package/files/buildCodeplay/sync-admob-nextgen.js +6 -5
- package/files/buildCodeplay/versions.json +2 -2
- package/files/finalrelease +1222 -1343
- package/files/take-screen-image.js +2 -2
- package/package.json +14 -5
- package/scripts/sync-files.js +80 -112
- package/scripts/uninstall.js +3 -123
- package/.gitattributes +0 -2
- package/files/buildCodeplay/codeplayBeforeBuild-6.4.js +0 -4510
- package/files/iap-install-2.js +0 -145
- /package/files/{scripts → scripts-common}/screenshot/background-decorations.js +0 -0
- /package/files/{scripts → scripts-common}/screenshot/frame-samples.js +0 -0
- /package/files/{scripts → scripts-common}/setup-baseline-profile.js +0 -0
|
@@ -1,98 +1,98 @@
|
|
|
1
|
-
const { spawn } = require("child_process");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
|
|
5
|
-
// Paths
|
|
6
|
-
//const projectRoot = path.join(__dirname, "..");
|
|
7
|
-
const projectRoot = process.cwd();
|
|
8
|
-
const androidPath = path.join(projectRoot, "android");
|
|
9
|
-
const capacitorConfigPath = path.join(projectRoot, "capacitor.config.json");
|
|
10
|
-
|
|
11
|
-
// Read capacitor.config.json
|
|
12
|
-
if (!fs.existsSync(capacitorConfigPath)) {
|
|
13
|
-
console.error("❌ capacitor.config.json not found!");
|
|
14
|
-
process.exit(1);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const config = JSON.parse(fs.readFileSync(capacitorConfigPath, "utf8"));
|
|
18
|
-
|
|
19
|
-
const buildOptions = config.android?.buildOptions;
|
|
20
|
-
|
|
21
|
-
if (!buildOptions) {
|
|
22
|
-
console.error("❌ android.buildOptions not found in capacitor.config.json");
|
|
23
|
-
process.exit(1);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Resolve keystore path (relative → absolute)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const storePassword = buildOptions.keystorePassword;
|
|
30
|
-
const keyAlias = buildOptions.keystoreAlias;
|
|
31
|
-
const keyPassword = buildOptions.keystoreAliasPassword;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const rawKeystorePath = buildOptions.keystorePath;
|
|
39
|
-
|
|
40
|
-
// First try normal resolve
|
|
41
|
-
let keystorePath = path.resolve(projectRoot, rawKeystorePath);
|
|
42
|
-
|
|
43
|
-
// If not found, try trimming one "../"
|
|
44
|
-
if (!fs.existsSync(keystorePath)) {
|
|
45
|
-
console.log("⚠️ Keystore not found, attempting path correction...");
|
|
46
|
-
|
|
47
|
-
const trimmedPath = rawKeystorePath.replace(/^\.\.\//, "");
|
|
48
|
-
keystorePath = path.resolve(projectRoot, trimmedPath);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Final validation
|
|
52
|
-
if (!fs.existsSync(keystorePath)) {
|
|
53
|
-
console.error("❌ Keystore file not found even after correction:", keystorePath);
|
|
54
|
-
process.exit(1);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
console.log("🔐 Using keystore:", keystorePath);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// Gradle args
|
|
69
|
-
const isWindows = process.platform === "win32";
|
|
70
|
-
const command = isWindows ? "cmd.exe" : "sh";
|
|
71
|
-
const args = [
|
|
72
|
-
...(isWindows ? ["/c", "gradlew.bat"] : ["./gradlew"]),
|
|
73
|
-
"assembleRelease",
|
|
74
|
-
`-Pandroid.injected.signing.store.file=${keystorePath}`,
|
|
75
|
-
`-Pandroid.injected.signing.store.password=${storePassword}`,
|
|
76
|
-
`-Pandroid.injected.signing.key.alias=${keyAlias}`,
|
|
77
|
-
`-Pandroid.injected.signing.key.password=${keyPassword}`,
|
|
78
|
-
];
|
|
79
|
-
|
|
80
|
-
// Run Gradle
|
|
81
|
-
const gradle = spawn(command, args, {
|
|
82
|
-
cwd: androidPath,
|
|
83
|
-
stdio: "inherit",
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
gradle.on("error", (error) => {
|
|
87
|
-
console.error("❌ Could not start Gradle:", error.message);
|
|
88
|
-
process.exit(1);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
gradle.on("close", (code) => {
|
|
92
|
-
if (code === 0) {
|
|
93
|
-
console.log("\n✅ Signed APK Generated Successfully!");
|
|
94
|
-
} else {
|
|
95
|
-
console.log("\n❌ Build Failed with code:", code);
|
|
96
|
-
process.exit(code ?? 1);
|
|
97
|
-
}
|
|
1
|
+
const { spawn } = require("child_process");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
|
|
5
|
+
// Paths
|
|
6
|
+
//const projectRoot = path.join(__dirname, "..");
|
|
7
|
+
const projectRoot = process.cwd();
|
|
8
|
+
const androidPath = path.join(projectRoot, "android");
|
|
9
|
+
const capacitorConfigPath = path.join(projectRoot, "capacitor.config.json");
|
|
10
|
+
|
|
11
|
+
// Read capacitor.config.json
|
|
12
|
+
if (!fs.existsSync(capacitorConfigPath)) {
|
|
13
|
+
console.error("❌ capacitor.config.json not found!");
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const config = JSON.parse(fs.readFileSync(capacitorConfigPath, "utf8"));
|
|
18
|
+
|
|
19
|
+
const buildOptions = config.android?.buildOptions;
|
|
20
|
+
|
|
21
|
+
if (!buildOptions) {
|
|
22
|
+
console.error("❌ android.buildOptions not found in capacitor.config.json");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Resolve keystore path (relative → absolute)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
const storePassword = buildOptions.keystorePassword;
|
|
30
|
+
const keyAlias = buildOptions.keystoreAlias;
|
|
31
|
+
const keyPassword = buildOptions.keystoreAliasPassword;
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
const rawKeystorePath = buildOptions.keystorePath;
|
|
39
|
+
|
|
40
|
+
// First try normal resolve
|
|
41
|
+
let keystorePath = path.resolve(projectRoot, rawKeystorePath);
|
|
42
|
+
|
|
43
|
+
// If not found, try trimming one "../"
|
|
44
|
+
if (!fs.existsSync(keystorePath)) {
|
|
45
|
+
console.log("⚠️ Keystore not found, attempting path correction...");
|
|
46
|
+
|
|
47
|
+
const trimmedPath = rawKeystorePath.replace(/^\.\.\//, "");
|
|
48
|
+
keystorePath = path.resolve(projectRoot, trimmedPath);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Final validation
|
|
52
|
+
if (!fs.existsSync(keystorePath)) {
|
|
53
|
+
console.error("❌ Keystore file not found even after correction:", keystorePath);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
console.log("🔐 Using keystore:", keystorePath);
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
// Gradle args
|
|
69
|
+
const isWindows = process.platform === "win32";
|
|
70
|
+
const command = isWindows ? "cmd.exe" : "sh";
|
|
71
|
+
const args = [
|
|
72
|
+
...(isWindows ? ["/c", "gradlew.bat"] : ["./gradlew"]),
|
|
73
|
+
"assembleRelease",
|
|
74
|
+
`-Pandroid.injected.signing.store.file=${keystorePath}`,
|
|
75
|
+
`-Pandroid.injected.signing.store.password=${storePassword}`,
|
|
76
|
+
`-Pandroid.injected.signing.key.alias=${keyAlias}`,
|
|
77
|
+
`-Pandroid.injected.signing.key.password=${keyPassword}`,
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
// Run Gradle
|
|
81
|
+
const gradle = spawn(command, args, {
|
|
82
|
+
cwd: androidPath,
|
|
83
|
+
stdio: "inherit",
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
gradle.on("error", (error) => {
|
|
87
|
+
console.error("❌ Could not start Gradle:", error.message);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
gradle.on("close", (code) => {
|
|
92
|
+
if (code === 0) {
|
|
93
|
+
console.log("\n✅ Signed APK Generated Successfully!");
|
|
94
|
+
} else {
|
|
95
|
+
console.log("\n❌ Build Failed with code:", code);
|
|
96
|
+
process.exit(code ?? 1);
|
|
97
|
+
}
|
|
98
98
|
});
|
|
@@ -1,11 +1,83 @@
|
|
|
1
|
-
// Version 6.
|
|
2
|
-
// Version 6.
|
|
1
|
+
// Version 6.7: deferred IAP startup, ownership-safe ads, and unified store preparation.
|
|
2
|
+
// Version 6.7: migrate AdMob files to ZIP-distributed folder packages.
|
|
3
|
+
// Version 6.7: recreate failed WebViews, defer background recovery, and suppress foreground recovery toasts.
|
|
3
4
|
const fs = require('fs');
|
|
4
5
|
const path = require('path');
|
|
5
6
|
const plist = require('plist');
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
|
|
10
|
+
// BEGIN IAP BUILD MIGRATION
|
|
11
|
+
const updateBuildEntrypoints = (scripts) => require('./project-scripts.cjs').updateBuildScripts(scripts);
|
|
12
|
+
|
|
13
|
+
const migrateIapStartup = (content, bootstrapImport) => {
|
|
14
|
+
let next = content;
|
|
15
|
+
const bootstrapPattern = /import\s*\{\s*initIAP\s*\}\s*from\s*['"][^'"]*\/IAP-bootstrap\.js['"]\s*;?/;
|
|
16
|
+
if (!bootstrapPattern.test(next)) {
|
|
17
|
+
next = next.replace(/import\s*\{([^}]*)\}\s*from\s*(['"])([^'"]*\/IAP-\d+(?:\.\d+)*\/IAP-check-And-LoadAd\.js)\2\s*;?/g,
|
|
18
|
+
(match, names, quote, source) => {
|
|
19
|
+
const imports = names.split(',').map(name => name.trim()).filter(Boolean);
|
|
20
|
+
if (!imports.includes('initIAP')) return match;
|
|
21
|
+
const remaining = imports.filter(name => name !== 'initIAP');
|
|
22
|
+
return remaining.length ? `import { ${remaining.join(', ')} } from ${quote}${source}${quote};` : '';
|
|
23
|
+
});
|
|
24
|
+
next = next.replace(/<script>\s*\r?\n/, match => `${match}import { initIAP } from '${bootstrapImport}';\n`);
|
|
25
|
+
}
|
|
26
|
+
if (!/\binitIAP\s*\(/.test(next)) {
|
|
27
|
+
const component = /(export\s+default\s*\([^)]*\)\s*=>\s*\{\s*\r?\n)/;
|
|
28
|
+
if (!component.test(next)) throw new Error('Unsupported Home component: cannot schedule IAP safely.');
|
|
29
|
+
next = next.replace(component, '$1 initIAP();\n');
|
|
30
|
+
}
|
|
31
|
+
return next;
|
|
32
|
+
};
|
|
33
|
+
// Identify existing Pro controls without replacing an application's Home layout.
|
|
34
|
+
// App-specific controls can opt in with the codeplay-iap-pro class.
|
|
35
|
+
const migrateHomeIapVisibility = (content, stateImport) => {
|
|
36
|
+
const template = content.match(/<template>[\s\S]*?<\/template>/);
|
|
37
|
+
if (!template) return content;
|
|
38
|
+
const stack = [];
|
|
39
|
+
const controls = new Map();
|
|
40
|
+
const tags = /<!--[\s\S]*?-->|<\/?[\w-]+\b(?:[^"'<>]|"[^"]*"|'[^']*')*>/g;
|
|
41
|
+
for (const match of template[0].matchAll(tags)) {
|
|
42
|
+
const tag = match[0];
|
|
43
|
+
if (tag.startsWith('<!--')) continue;
|
|
44
|
+
const name = tag.match(/^<\/?([\w-]+)/)[1].toLowerCase();
|
|
45
|
+
if (tag.startsWith('</')) {
|
|
46
|
+
const index = stack.map(item => item.name).lastIndexOf(name);
|
|
47
|
+
if (index >= 0) stack.length = index;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const classMatch = tag.match(/\bclass\s*=\s*(["'])([\s\S]*?)\1/);
|
|
51
|
+
const classes = classMatch?.[2] || '';
|
|
52
|
+
const node = { name, tag, index: template.index + match.index, classes };
|
|
53
|
+
const clickable = item => /(?:@click|\bdata-iap-pro)\s*=/.test(item.tag) || ['a', 'button'].includes(item.name) || /\b(?:link|codeplay-iap-pro)\b/.test(item.classes);
|
|
54
|
+
if (/\b(?:trPro|clsSubscribeBtn|codeplay-iap-pro)\b/.test(classes) || /@click\s*=\s*["']\$\{\s*subscribeOrProLink\s*\}/.test(tag)) {
|
|
55
|
+
const control = clickable(node) ? node : [...stack].reverse().find(clickable) || (/\bclsSubscribeBtn\b/.test(classes) ? node : null);
|
|
56
|
+
if (control) controls.set(control.index, control);
|
|
57
|
+
}
|
|
58
|
+
if (!/\/\s*>$/.test(tag) && !['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'].includes(name)) stack.push(node);
|
|
59
|
+
}
|
|
60
|
+
if (!controls.size) return content;
|
|
61
|
+
const gate = stateImport ? "${isIAPEnabledForCurrentStore() ? '' : 'display-none'}" : "${false ? '' : 'display-none'}";
|
|
62
|
+
let next = content;
|
|
63
|
+
for (const control of [...controls.values()].sort((a, b) => b.index - a.index)) {
|
|
64
|
+
const classes = control.classes
|
|
65
|
+
.replace(/\$\{(?:isIAPEnabledForCurrentStore\(\)|false)\s*\?\s*''\s*:\s*'display-none'\s*\}/g, '')
|
|
66
|
+
.split(/\s+/).filter(name => name && !/^hideFor(?:Mi|Vivo|Huawei|Oppo|Amazon|Samsung|Playstore|PlayStore|Ios|iOS)$/.test(name) && name !== 'codeplay-iap-pro');
|
|
67
|
+
const value = `${classes.join(' ')} codeplay-iap-pro ${gate}`.trim();
|
|
68
|
+
const tag = /\bclass\s*=/.test(control.tag)
|
|
69
|
+
? control.tag.replace(/\bclass\s*=\s*(["'])([\s\S]*?)\1/, () => `class="${value}"`)
|
|
70
|
+
: control.tag.replace(/^<[\w-]+/, match => `${match} class="${value}"`);
|
|
71
|
+
next = next.slice(0, control.index) + tag + next.slice(control.index + control.tag.length);
|
|
72
|
+
}
|
|
73
|
+
if (stateImport && !/import\s*\{[^}]*\bisIAPEnabledForCurrentStore\b[^}]*\}\s*from\s*['"][^'"]*\/IAP-state\.js['"]/.test(next)) {
|
|
74
|
+
if (!next.includes('<script>')) throw new Error('Cannot migrate Pro visibility: Home has no script block.');
|
|
75
|
+
next = next.replace(/<script>(?:[ \t]*\r?\n)?/, match => `${match}import { isIAPEnabledForCurrentStore } from '${stateImport}';\n`);
|
|
76
|
+
}
|
|
77
|
+
return next;
|
|
78
|
+
};
|
|
79
|
+
// END IAP BUILD MIGRATION
|
|
80
|
+
|
|
9
81
|
const { execSync } = require("child_process");
|
|
10
82
|
|
|
11
83
|
|
|
@@ -95,10 +167,10 @@ const getLatestVersionedFileName = (dir, pattern) => {
|
|
|
95
167
|
/* const requiredPlugins = [
|
|
96
168
|
|
|
97
169
|
{ pattern: /backbutton-(\d+\.\d+)\.js$/, minVersion: '2.0', required: true, baseDir: 'js',mandatoryUpdate: true},
|
|
98
|
-
|
|
170
|
+
|
|
99
171
|
|
|
100
172
|
{ pattern: /common-(\d+\.\d+)(?:-beta-(\d+))?\.js$/, minVersion: '6.0', required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
101
|
-
|
|
173
|
+
|
|
102
174
|
{ pattern: /localization_settings-(\d+\.\d+)\.js$/, minVersion: '1.1', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
103
175
|
{ pattern: /localization-(\d+\.\d+)\.js$/, minVersion: '1.5', required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
104
176
|
{ pattern: /localNotification-(\d+\.\d+)\.js$/, minVersion: '2.2', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
@@ -110,8 +182,8 @@ const getLatestVersionedFileName = (dir, pattern) => {
|
|
|
110
182
|
{ pattern: /video-player-(\d+\.\d+)\.js$/, minVersion: '1.5', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
111
183
|
{ pattern: /image-cropper-(\d+\.\d+)\.js$/, minVersion: '1.1', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
112
184
|
{ pattern: /common-(\d+\.\d+)\.less$/, minVersion: '1.6', required: true, baseDir: 'assets/css',mandatoryUpdate: false },
|
|
113
|
-
|
|
114
|
-
|
|
185
|
+
|
|
186
|
+
|
|
115
187
|
// New folders
|
|
116
188
|
{ pattern: /IAP-(\d+\.\d+)$/, minVersion: '2.8', isFolder: true , required: true, baseDir: 'js/Ads',mandatoryUpdate: true },
|
|
117
189
|
{ pattern: /editor-(\d+\.\d+)$/, minVersion: '1.9', isFolder: true, required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
@@ -120,11 +192,11 @@ const getLatestVersionedFileName = (dir, pattern) => {
|
|
|
120
192
|
|
|
121
193
|
|
|
122
194
|
{ pattern: /certificatejs-(\d+\.\d+)$/, minVersion: '1.6', isFolder: true , required: true, baseDir: 'certificate',mandatoryUpdate: true }
|
|
123
|
-
|
|
195
|
+
|
|
124
196
|
]; */
|
|
125
197
|
|
|
126
198
|
|
|
127
|
-
const ROOT_DIR = path.join(
|
|
199
|
+
const ROOT_DIR = path.join(process.cwd(), "src");
|
|
128
200
|
|
|
129
201
|
function requireOrInstall(packageName) {
|
|
130
202
|
try {
|
|
@@ -230,6 +302,7 @@ function loadRequiredPlugins() {
|
|
|
230
302
|
!/^admob-(?:emi-)?nextgen$/i.test(String(p.name || '')) && !/^onesignal(?:-|$)/i.test(String(p.name || '')) && !/onesignal/i.test(String(p.pattern || ''))
|
|
231
303
|
).map(p => ({
|
|
232
304
|
...p,
|
|
305
|
+
minVersion: p.name === 'IAP' && compareVersionStrings(p.minVersion, '4.6') < 0 ? '4.6' : p.minVersion,
|
|
233
306
|
pattern: new RegExp(p.pattern)
|
|
234
307
|
}));
|
|
235
308
|
|
|
@@ -289,6 +362,12 @@ function getLatestVersion(packageName) {
|
|
|
289
362
|
|
|
290
363
|
function checkPackageVersion() {
|
|
291
364
|
const packageName = 'codeplay-common';
|
|
365
|
+
const appPackage = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
366
|
+
const declaredPackage = appPackage.dependencies?.[packageName] || appPackage.devDependencies?.[packageName] || '';
|
|
367
|
+
if (/^(?:file:|link:|workspace:)/.test(declaredPackage)) {
|
|
368
|
+
console.log('Using local codeplay-common source; skipping registry replacement.');
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
292
371
|
const installedVersion = getInstalledVersion(packageName);
|
|
293
372
|
const latestVersion = getLatestVersion(packageName);
|
|
294
373
|
|
|
@@ -298,9 +377,9 @@ function checkPackageVersion() {
|
|
|
298
377
|
return;
|
|
299
378
|
}
|
|
300
379
|
|
|
301
|
-
if (installedVersion
|
|
380
|
+
if (compareVersionStrings(installedVersion, latestVersion) < 0) {
|
|
302
381
|
console.log(`${packageName} is outdated (installed: ${installedVersion}, latest: ${latestVersion}). Updating now...`);
|
|
303
|
-
|
|
382
|
+
|
|
304
383
|
try {
|
|
305
384
|
execSync(`npm uninstall ${packageName}`, { stdio: 'inherit' });
|
|
306
385
|
execSync(`npm install ${packageName}`, { stdio: 'inherit' });
|
|
@@ -424,7 +503,7 @@ const checkAppUniqueId=()=>{
|
|
|
424
503
|
|
|
425
504
|
if (!orientation) {
|
|
426
505
|
logErrorMessage+='❌ Missing android.ORIENTATION option in capacitor.config.json.\n';
|
|
427
|
-
}
|
|
506
|
+
}
|
|
428
507
|
|
|
429
508
|
else if(orientation!="portrait" && orientation!="landscape" && orientation!="auto")
|
|
430
509
|
{
|
|
@@ -555,34 +634,19 @@ const getRelativeModuleImport = (sourceFile, targetFile) => {
|
|
|
555
634
|
return relativePath;
|
|
556
635
|
};
|
|
557
636
|
|
|
558
|
-
const addInitIapToExistingImport = (content) => {
|
|
559
|
-
const iapImportRegex = /import\s*\{([^}]*)\}\s*from\s*(['"])([^'"]*\/IAP-\d+(?:\.\d+)*\/IAP-check-And-LoadAd\.js)\2\s*;?/;
|
|
560
|
-
const match = content.match(iapImportRegex);
|
|
561
|
-
if (!match || /\binitIAP\b/.test(match[1])) return content;
|
|
562
|
-
|
|
563
|
-
const importNames = match[1].trim();
|
|
564
|
-
const nextImportNames = importNames ? `initIAP, ${importNames}` : "initIAP";
|
|
565
|
-
return content.replace(iapImportRegex, `import { ${nextImportNames} } from ${match[2]}${match[3]}${match[2]};`);
|
|
566
|
-
};
|
|
567
|
-
|
|
568
|
-
const addInitIapCall = (content) => {
|
|
569
|
-
if (/\binitIAP\s*\(/.test(content)) return content;
|
|
570
|
-
|
|
571
|
-
const pageInitRegex = /(\$on\(\s*(['"])pageInit\2\s*,\s*(?:async\s*)?\(\)\s*=>\s*\{\s*\r?\n)/;
|
|
572
|
-
if (pageInitRegex.test(content)) {
|
|
573
|
-
return content.replace(pageInitRegex, "$1 initIAP();\n");
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
const componentStartRegex = /(export\s+default\s*\([^)]*\)\s*=>\s*\{\s*\r?\n)/;
|
|
577
|
-
if (componentStartRegex.test(content)) {
|
|
578
|
-
return content.replace(componentStartRegex, "$1 initIAP();\n");
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
throw new Error("Unable to find a Framework7 component or pageInit lifecycle for IAP startup.");
|
|
582
|
-
};
|
|
583
|
-
|
|
584
637
|
const ensureIapStartupOnHomePage = () => {
|
|
585
638
|
const iapConfig = getAdmobIapConfig()?.IAP;
|
|
639
|
+
const visibilityHome = getHomePagePath();
|
|
640
|
+
const visibilityIap = getLatestIapDir();
|
|
641
|
+
const statePath = visibilityIap && path.join(visibilityIap, 'IAP-state.js');
|
|
642
|
+
if (visibilityHome) {
|
|
643
|
+
const original = fs.readFileSync(visibilityHome, 'utf8');
|
|
644
|
+
const next = migrateHomeIapVisibility(original, statePath && fs.existsSync(statePath) ? getRelativeModuleImport(visibilityHome, statePath) : null);
|
|
645
|
+
if (next !== original) {
|
|
646
|
+
fs.writeFileSync(visibilityHome, next, 'utf8');
|
|
647
|
+
console.log(`✅ Updated shared Pro-button visibility in ${path.relative(process.cwd(), visibilityHome)}.`);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
586
650
|
if (!isAnyIapStoreEnabled(iapConfig)) {
|
|
587
651
|
console.log("ℹ️ IAP is disabled for every store. AdMob will use direct startup.");
|
|
588
652
|
return;
|
|
@@ -605,26 +669,15 @@ const ensureIapStartupOnHomePage = () => {
|
|
|
605
669
|
|
|
606
670
|
let content = fs.readFileSync(homePagePath, "utf8");
|
|
607
671
|
const originalContent = content;
|
|
608
|
-
const
|
|
609
|
-
|
|
610
|
-
content =
|
|
611
|
-
|
|
612
|
-
if (!staticInitImportRegex.test(content)) {
|
|
613
|
-
const relativeImport = getRelativeModuleImport(homePagePath, iapModulePath);
|
|
614
|
-
const scriptStartRegex = /<script>\s*\r?\n/;
|
|
615
|
-
if (!scriptStartRegex.test(content)) {
|
|
616
|
-
throw new Error(`Unable to find the script block in ${homePagePath}`);
|
|
617
|
-
}
|
|
618
|
-
content = content.replace(scriptStartRegex, `$&import { initIAP } from '${relativeImport}';\n`);
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
content = addInitIapCall(content);
|
|
672
|
+
const bootstrapPath = path.join(latestIapDir, 'IAP-bootstrap.js');
|
|
673
|
+
if (!fs.existsSync(bootstrapPath)) throw new Error('IAP 4.6 or newer is required for deferred startup.');
|
|
674
|
+
content = migrateIapStartup(content, getRelativeModuleImport(homePagePath, bootstrapPath));
|
|
622
675
|
|
|
623
676
|
if (content !== originalContent) {
|
|
624
677
|
fs.writeFileSync(homePagePath, content, "utf8");
|
|
625
|
-
console.log(`✅ Added
|
|
678
|
+
console.log(`✅ Added background IAP startup to ${path.relative(process.cwd(), homePagePath)}.`);
|
|
626
679
|
} else {
|
|
627
|
-
console.log(`ℹ️
|
|
680
|
+
console.log(`ℹ️ Background IAP startup already configured in ${path.relative(process.cwd(), homePagePath)}.`);
|
|
628
681
|
}
|
|
629
682
|
};
|
|
630
683
|
|
|
@@ -647,7 +700,7 @@ const ensureIapStartupOnHomePage = () => {
|
|
|
647
700
|
//const path = require("path");
|
|
648
701
|
//const { execSync } = require("child_process");
|
|
649
702
|
|
|
650
|
-
const jsDir = path.join(
|
|
703
|
+
const jsDir = path.join(process.cwd(), "src", "js");
|
|
651
704
|
|
|
652
705
|
// 🔍 Detect OLD structure
|
|
653
706
|
const oldEditorDirs = fs.readdirSync(jsDir)
|
|
@@ -792,9 +845,9 @@ else {
|
|
|
792
845
|
|
|
793
846
|
const saveToGalleryAndSaveFileCheck_iOS = async () => {
|
|
794
847
|
|
|
795
|
-
const SOURCE_ROOT = path.resolve(
|
|
848
|
+
const SOURCE_ROOT = path.resolve(process.cwd(), 'src');
|
|
796
849
|
const EXCLUDED_DIR = path.join(SOURCE_ROOT, 'js', 'Ads');
|
|
797
|
-
const ANDROID_MANIFEST_PATH = path.resolve(
|
|
850
|
+
const ANDROID_MANIFEST_PATH = path.resolve(process.cwd(), 'android/app/src/main/AndroidManifest.xml');
|
|
798
851
|
|
|
799
852
|
|
|
800
853
|
// Skip comments and unrelated strings; match static/dynamic imports, re-exports and require.
|
|
@@ -816,7 +869,7 @@ You are using a direct version-based path like: editor/editor-x.x/editor.js
|
|
|
816
869
|
|
|
817
870
|
👉 Please use the proper alias or updated import method.
|
|
818
871
|
Example: import { ... } from '@editor'
|
|
819
|
-
|
|
872
|
+
|
|
820
873
|
⚠️ Do not use version-based paths in imports.
|
|
821
874
|
👉 Please add this manually in vite.config.js:
|
|
822
875
|
|
|
@@ -838,7 +891,7 @@ const SKIP_FILES = [
|
|
|
838
891
|
|
|
839
892
|
|
|
840
893
|
|
|
841
|
-
const STATUSBAR_FILE = path.resolve(
|
|
894
|
+
const STATUSBAR_FILE = path.resolve(process.cwd(), 'src/js/common-configuration.js');
|
|
842
895
|
const STATUSBAR_REGEX = /^(?!\s*\/\/).*Capacitor\.Plugins\.StatusBar\.setStyle/m;
|
|
843
896
|
|
|
844
897
|
|
|
@@ -1151,7 +1204,7 @@ const routes = [
|
|
|
1151
1204
|
},
|
|
1152
1205
|
}]
|
|
1153
1206
|
`);
|
|
1154
|
-
|
|
1207
|
+
|
|
1155
1208
|
badImports.forEach(({ line, number }) => {
|
|
1156
1209
|
console.error(`${number}: ${line}`);
|
|
1157
1210
|
});
|
|
@@ -1394,8 +1447,8 @@ if (updated) {
|
|
|
1394
1447
|
|
|
1395
1448
|
// Build the path dynamically like you requested
|
|
1396
1449
|
const gradlePath = path.join(
|
|
1397
|
-
process.cwd(),
|
|
1398
|
-
'android',
|
|
1450
|
+
process.cwd(),
|
|
1451
|
+
'android',
|
|
1399
1452
|
'build.gradle'
|
|
1400
1453
|
);
|
|
1401
1454
|
|
|
@@ -1614,11 +1667,11 @@ function validateAndroidBuildOptions() {
|
|
|
1614
1667
|
const targetAppId=config.appId
|
|
1615
1668
|
|
|
1616
1669
|
const buildOptions = config.android?.buildOptions;
|
|
1617
|
-
|
|
1670
|
+
|
|
1618
1671
|
if (!buildOptions) {
|
|
1619
1672
|
console.log('❌ Missing android.buildOptions in capacitor.config.json.');
|
|
1620
1673
|
process.exit(1);
|
|
1621
|
-
}
|
|
1674
|
+
}
|
|
1622
1675
|
|
|
1623
1676
|
const requiredProps = [
|
|
1624
1677
|
'keystorePath',
|
|
@@ -1630,13 +1683,13 @@ function validateAndroidBuildOptions() {
|
|
|
1630
1683
|
];
|
|
1631
1684
|
|
|
1632
1685
|
const missing = requiredProps.filter(prop => !buildOptions[prop]);
|
|
1633
|
-
|
|
1686
|
+
|
|
1634
1687
|
if (missing.length > 0) {
|
|
1635
1688
|
console.log('❌ Missing properties android.buildOptions in capacitor.config.json.');
|
|
1636
1689
|
process.exit(1);
|
|
1637
1690
|
}
|
|
1638
1691
|
|
|
1639
|
-
|
|
1692
|
+
|
|
1640
1693
|
const keystorePath=buildOptions.keystorePath
|
|
1641
1694
|
const keyFileName = path.basename(keystorePath);
|
|
1642
1695
|
|
|
@@ -1826,7 +1879,7 @@ try {
|
|
|
1826
1879
|
_admobConfig = getAdMobConfig();
|
|
1827
1880
|
|
|
1828
1881
|
|
|
1829
|
-
|
|
1882
|
+
|
|
1830
1883
|
|
|
1831
1884
|
|
|
1832
1885
|
// Proceed only if ADMOB_ENABLED is true
|
|
@@ -2170,7 +2223,9 @@ async function syncAgentInstructions() {
|
|
|
2170
2223
|
|
|
2171
2224
|
const zipName = `${AGENT_INSTRUCTIONS_ZIP_PREFIX}-${remoteVersion}.zip`;
|
|
2172
2225
|
const url = `https://htmlcodeplay.com/code-play-plugin/${zipName}`;
|
|
2173
|
-
const
|
|
2226
|
+
const agentTempRoot = path.join(process.cwd(), "agent-temp", "agent-instructions");
|
|
2227
|
+
fs.mkdirSync(agentTempRoot, { recursive: true });
|
|
2228
|
+
const tempRoot = fs.mkdtempSync(path.join(agentTempRoot, "codeplay-agents-"));
|
|
2174
2229
|
const zipPath = path.join(tempRoot, zipName);
|
|
2175
2230
|
const extractPath = path.join(tempRoot, "extracted");
|
|
2176
2231
|
|
|
@@ -2248,7 +2303,9 @@ if (baseName === "common") {
|
|
|
2248
2303
|
if (ext === ".less") pluginKey = "common-less";
|
|
2249
2304
|
}
|
|
2250
2305
|
|
|
2251
|
-
const
|
|
2306
|
+
const advertisedVersion = versions[pluginKey];
|
|
2307
|
+
const latestVersion = baseName === 'IAP' && (!advertisedVersion || compareVersionStrings(advertisedVersion, pluginDef.minVersion) < 0)
|
|
2308
|
+
? pluginDef.minVersion : advertisedVersion;
|
|
2252
2309
|
|
|
2253
2310
|
if (!latestVersion) {
|
|
2254
2311
|
console.log(`❌ No version entry for ${baseName}`);
|
|
@@ -2269,12 +2326,17 @@ if (pluginDef.isFolder) {
|
|
|
2269
2326
|
|
|
2270
2327
|
if (!(await urlExists(url))) return false;
|
|
2271
2328
|
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2329
|
+
const stagingRoot = path.join(process.cwd(), 'agent-temp', 'iap-package-sync');
|
|
2330
|
+
fs.mkdirSync(stagingRoot, { recursive: true });
|
|
2331
|
+
const staging = fs.mkdtempSync(path.join(stagingRoot, 'package-'));
|
|
2332
|
+
await downloadAndExtractZip(url, staging);
|
|
2333
|
+
if (baseName === 'IAP' && ['IAP-check-And-LoadAd.js', 'IAP-bootstrap.js', 'IAP-state.js', 'IAP-store.js'].some(name => !fs.existsSync(path.join(staging, name)))) throw new Error('Invalid IAP archive');
|
|
2334
|
+
if (fs.existsSync(newPath)) throw new Error('Replacement folder already exists; existing sources preserved.');
|
|
2335
|
+
fs.renameSync(staging, newPath);
|
|
2336
|
+
sourceFileInventory = null;
|
|
2276
2337
|
updateImports(pluginInfo.name, `${baseName}-${latestVersion}`);
|
|
2277
2338
|
|
|
2339
|
+
fs.rmSync(oldPath, { recursive: true, force: true });
|
|
2278
2340
|
// ✅ ADD THIS
|
|
2279
2341
|
writeUpdateLine(`${pluginInfo.name} -> ${baseName}-${latestVersion}`);
|
|
2280
2342
|
|
|
@@ -2352,7 +2414,7 @@ existingFiles.forEach(file => {
|
|
|
2352
2414
|
fs.unlinkSync(oldPath);
|
|
2353
2415
|
|
|
2354
2416
|
console.log(`🗑 Removed old file → ${file}`);
|
|
2355
|
-
//writeUpdateLine(`Removed old file: ${file}`);
|
|
2417
|
+
//writeUpdateLine(`Removed old file: ${file}`);
|
|
2356
2418
|
}
|
|
2357
2419
|
|
|
2358
2420
|
});
|
|
@@ -2415,7 +2477,7 @@ async function loadPluginVersions() {
|
|
|
2415
2477
|
if (!plugin.name) return;
|
|
2416
2478
|
|
|
2417
2479
|
if (versions[plugin.name]) {
|
|
2418
|
-
plugin.minVersion = versions[plugin.name];
|
|
2480
|
+
if (compareVersionStrings(versions[plugin.name], plugin.minVersion) > 0) plugin.minVersion = versions[plugin.name];
|
|
2419
2481
|
}
|
|
2420
2482
|
|
|
2421
2483
|
});
|
|
@@ -2518,7 +2580,7 @@ function checkPlugins() {
|
|
|
2518
2580
|
} */
|
|
2519
2581
|
|
|
2520
2582
|
|
|
2521
|
-
|
|
2583
|
+
|
|
2522
2584
|
|
|
2523
2585
|
|
|
2524
2586
|
if (hasMandatoryUpdate) {
|
|
@@ -2625,14 +2687,14 @@ if (hasMandatoryUpdate) {
|
|
|
2625
2687
|
|
|
2626
2688
|
|
|
2627
2689
|
|
|
2628
|
-
const localizationBaseDir = path.join(
|
|
2690
|
+
const localizationBaseDir = path.join(process.cwd(), "src", "js", "localization");
|
|
2629
2691
|
|
|
2630
2692
|
// ======================================================
|
|
2631
2693
|
// 🌐 LOCALIZATION CHECK (FULLY DYNAMIC)
|
|
2632
2694
|
// ======================================================
|
|
2633
2695
|
|
|
2634
2696
|
|
|
2635
|
-
const jsRootDir = path.join(
|
|
2697
|
+
const jsRootDir = path.join(process.cwd(), "src", "js");
|
|
2636
2698
|
|
|
2637
2699
|
// 🔍 Detect OLD localization files in root js/
|
|
2638
2700
|
const oldLocalizationFiles = fs.readdirSync(jsRootDir)
|
|
@@ -3713,6 +3775,7 @@ const ensureIapDesignInCapacitorConfig = (iapConfig) => {
|
|
|
3713
3775
|
};
|
|
3714
3776
|
|
|
3715
3777
|
const getCurrentStoreId = () => {
|
|
3778
|
+
if (buildPlatform === 'ios') return 6;
|
|
3716
3779
|
const envStoreId = Number(process.env.VITE_STORE_ID);
|
|
3717
3780
|
if (Number.isInteger(envStoreId) && envStoreId > 0) return envStoreId;
|
|
3718
3781
|
|
|
@@ -3900,6 +3963,17 @@ const syncRevenueCatIapSetup = () => {
|
|
|
3900
3963
|
console.log(`ℹ️ RevenueCat package is not required for store id ${storeId}.`);
|
|
3901
3964
|
}
|
|
3902
3965
|
|
|
3966
|
+
const samsungEnabled = storeId === 2 && iapConfig.samsung === true;
|
|
3967
|
+
const samsungPackagePath = path.join(process.cwd(), 'node_modules', 'cordova-plugin-samsungiap', 'package.json');
|
|
3968
|
+
const samsungVersion = fs.existsSync(samsungPackagePath) ? JSON.parse(fs.readFileSync(samsungPackagePath, 'utf8')).version : '0';
|
|
3969
|
+
if (samsungEnabled && (!isPackageAvailable('cordova-plugin-samsungiap') || compareVersionStrings(samsungVersion, '2.0.0') < 0)) {
|
|
3970
|
+
runNpmCommand('npm install cordova-plugin-samsungiap@^2.0.0');
|
|
3971
|
+
packageChanged = true;
|
|
3972
|
+
} else if (!samsungEnabled && isPackageAvailable('cordova-plugin-samsungiap')) {
|
|
3973
|
+
runNpmCommand('npm uninstall cordova-plugin-samsungiap');
|
|
3974
|
+
packageChanged = true;
|
|
3975
|
+
}
|
|
3976
|
+
ensureAndroidPermission('com.samsung.android.iap.permission.BILLING', samsungEnabled);
|
|
3903
3977
|
ensureAndroidPermission("com.android.vending.BILLING", store?.usesGoogleBilling === true && revenueCatEnabledForCurrentStore);
|
|
3904
3978
|
|
|
3905
3979
|
if (iapConfig.samsung === true && revenueCatEnabled) {
|
|
@@ -4169,8 +4243,8 @@ const validateAndRestoreSignDetails=()=>{
|
|
|
4169
4243
|
|
|
4170
4244
|
|
|
4171
4245
|
const filePath = path.join(
|
|
4172
|
-
|
|
4173
|
-
"
|
|
4246
|
+
process.cwd(),
|
|
4247
|
+
"node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java"
|
|
4174
4248
|
);
|
|
4175
4249
|
|
|
4176
4250
|
const SYSTEM_BARS_PATCH_MARKER = "CODEPLAY_KEYBOARD_INSET_FIX";
|
|
@@ -4388,17 +4462,23 @@ function syncAndroidCordovaResourceKeep() {
|
|
|
4388
4462
|
}
|
|
4389
4463
|
|
|
4390
4464
|
async function main() {
|
|
4465
|
+
const buildPackage = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
4466
|
+
const buildScripts = updateBuildEntrypoints(buildPackage.scripts || {});
|
|
4467
|
+
if (JSON.stringify(buildScripts) !== JSON.stringify(buildPackage.scripts)) {
|
|
4468
|
+
buildPackage.scripts = buildScripts;
|
|
4469
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(buildPackage, null, 2) + '\n');
|
|
4470
|
+
}
|
|
4391
4471
|
validateThemeFolderLocation();
|
|
4392
4472
|
validateAndRestoreSignDetails();
|
|
4393
4473
|
ensureMandatoryCapacitorPlugins();
|
|
4394
4474
|
|
|
4395
4475
|
await loadPluginVersions(); // 🔥 NEW
|
|
4396
4476
|
await syncAgentInstructions();
|
|
4477
|
+
await checkPlugins();
|
|
4397
4478
|
|
|
4398
4479
|
await syncAdmobNextgenMigration();
|
|
4399
4480
|
syncCodeplaySystemBarsPackage();
|
|
4400
4481
|
syncSystemBarsSafeAreaMigration();
|
|
4401
|
-
await checkPlugins();
|
|
4402
4482
|
ensureIapStartupOnHomePage();
|
|
4403
4483
|
syncRevenueCatIapSetup();
|
|
4404
4484
|
syncFirebaseAnalyticsSetup();
|