codeplay-common 4.9.9 → 4.10.1
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 +33 -17
- package/README.md +24 -10
- package/RELEASE_NOTES.md +31 -15
- 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} +179 -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 +25 -25
- 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,11 +1,90 @@
|
|
|
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
|
|
|
8
|
+
// Preserve comments, strings, and custom tree-shaking objects/functions.
|
|
9
|
+
// Only migrate the explicit boolean opt-out used by older Codeplay configs.
|
|
10
|
+
const migrateViteTreeShaking = (content) => content.replace(
|
|
11
|
+
/\/\*[\s\S]*?\*\/|\/\/[^\r\n]*|"(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'|`(?:\\[\s\S]|[^`\\])*`|\btreeshake([ \t]*:[ \t]*)false\b/g,
|
|
12
|
+
(match, separator) => separator === undefined ? match : `treeshake${separator}true`
|
|
13
|
+
);
|
|
14
|
+
|
|
7
15
|
|
|
8
16
|
|
|
17
|
+
// BEGIN IAP BUILD MIGRATION
|
|
18
|
+
const updateBuildEntrypoints = (scripts) => require('./project-scripts.cjs').updateBuildScripts(scripts);
|
|
19
|
+
|
|
20
|
+
const migrateIapStartup = (content, bootstrapImport) => {
|
|
21
|
+
let next = content;
|
|
22
|
+
const bootstrapPattern = /import\s*\{\s*initIAP\s*\}\s*from\s*['"][^'"]*\/IAP-bootstrap\.js['"]\s*;?/;
|
|
23
|
+
if (!bootstrapPattern.test(next)) {
|
|
24
|
+
next = next.replace(/import\s*\{([^}]*)\}\s*from\s*(['"])([^'"]*\/IAP-\d+(?:\.\d+)*\/IAP-check-And-LoadAd\.js)\2\s*;?/g,
|
|
25
|
+
(match, names, quote, source) => {
|
|
26
|
+
const imports = names.split(',').map(name => name.trim()).filter(Boolean);
|
|
27
|
+
if (!imports.includes('initIAP')) return match;
|
|
28
|
+
const remaining = imports.filter(name => name !== 'initIAP');
|
|
29
|
+
return remaining.length ? `import { ${remaining.join(', ')} } from ${quote}${source}${quote};` : '';
|
|
30
|
+
});
|
|
31
|
+
next = next.replace(/<script>\s*\r?\n/, match => `${match}import { initIAP } from '${bootstrapImport}';\n`);
|
|
32
|
+
}
|
|
33
|
+
if (!/\binitIAP\s*\(/.test(next)) {
|
|
34
|
+
const component = /(export\s+default\s*\([^)]*\)\s*=>\s*\{\s*\r?\n)/;
|
|
35
|
+
if (!component.test(next)) throw new Error('Unsupported Home component: cannot schedule IAP safely.');
|
|
36
|
+
next = next.replace(component, '$1 initIAP();\n');
|
|
37
|
+
}
|
|
38
|
+
return next;
|
|
39
|
+
};
|
|
40
|
+
// Identify existing Pro controls without replacing an application's Home layout.
|
|
41
|
+
// App-specific controls can opt in with the codeplay-iap-pro class.
|
|
42
|
+
const migrateHomeIapVisibility = (content, stateImport) => {
|
|
43
|
+
const template = content.match(/<template>[\s\S]*?<\/template>/);
|
|
44
|
+
if (!template) return content;
|
|
45
|
+
const stack = [];
|
|
46
|
+
const controls = new Map();
|
|
47
|
+
const tags = /<!--[\s\S]*?-->|<\/?[\w-]+\b(?:[^"'<>]|"[^"]*"|'[^']*')*>/g;
|
|
48
|
+
for (const match of template[0].matchAll(tags)) {
|
|
49
|
+
const tag = match[0];
|
|
50
|
+
if (tag.startsWith('<!--')) continue;
|
|
51
|
+
const name = tag.match(/^<\/?([\w-]+)/)[1].toLowerCase();
|
|
52
|
+
if (tag.startsWith('</')) {
|
|
53
|
+
const index = stack.map(item => item.name).lastIndexOf(name);
|
|
54
|
+
if (index >= 0) stack.length = index;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const classMatch = tag.match(/\bclass\s*=\s*(["'])([\s\S]*?)\1/);
|
|
58
|
+
const classes = classMatch?.[2] || '';
|
|
59
|
+
const node = { name, tag, index: template.index + match.index, classes };
|
|
60
|
+
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);
|
|
61
|
+
if (/\b(?:trPro|clsSubscribeBtn|codeplay-iap-pro)\b/.test(classes) || /@click\s*=\s*["']\$\{\s*subscribeOrProLink\s*\}/.test(tag)) {
|
|
62
|
+
const control = clickable(node) ? node : [...stack].reverse().find(clickable) || (/\bclsSubscribeBtn\b/.test(classes) ? node : null);
|
|
63
|
+
if (control) controls.set(control.index, control);
|
|
64
|
+
}
|
|
65
|
+
if (!/\/\s*>$/.test(tag) && !['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'].includes(name)) stack.push(node);
|
|
66
|
+
}
|
|
67
|
+
if (!controls.size) return content;
|
|
68
|
+
const gate = stateImport ? "${isIAPEnabledForCurrentStore() ? '' : 'display-none'}" : "${false ? '' : 'display-none'}";
|
|
69
|
+
let next = content;
|
|
70
|
+
for (const control of [...controls.values()].sort((a, b) => b.index - a.index)) {
|
|
71
|
+
const classes = control.classes
|
|
72
|
+
.replace(/\$\{(?:isIAPEnabledForCurrentStore\(\)|false)\s*\?\s*''\s*:\s*'display-none'\s*\}/g, '')
|
|
73
|
+
.split(/\s+/).filter(name => name && !/^hideFor(?:Mi|Vivo|Huawei|Oppo|Amazon|Samsung|Playstore|PlayStore|Ios|iOS)$/.test(name) && name !== 'codeplay-iap-pro');
|
|
74
|
+
const value = `${classes.join(' ')} codeplay-iap-pro ${gate}`.trim();
|
|
75
|
+
const tag = /\bclass\s*=/.test(control.tag)
|
|
76
|
+
? control.tag.replace(/\bclass\s*=\s*(["'])([\s\S]*?)\1/, () => `class="${value}"`)
|
|
77
|
+
: control.tag.replace(/^<[\w-]+/, match => `${match} class="${value}"`);
|
|
78
|
+
next = next.slice(0, control.index) + tag + next.slice(control.index + control.tag.length);
|
|
79
|
+
}
|
|
80
|
+
if (stateImport && !/import\s*\{[^}]*\bisIAPEnabledForCurrentStore\b[^}]*\}\s*from\s*['"][^'"]*\/IAP-state\.js['"]/.test(next)) {
|
|
81
|
+
if (!next.includes('<script>')) throw new Error('Cannot migrate Pro visibility: Home has no script block.');
|
|
82
|
+
next = next.replace(/<script>(?:[ \t]*\r?\n)?/, match => `${match}import { isIAPEnabledForCurrentStore } from '${stateImport}';\n`);
|
|
83
|
+
}
|
|
84
|
+
return next;
|
|
85
|
+
};
|
|
86
|
+
// END IAP BUILD MIGRATION
|
|
87
|
+
|
|
9
88
|
const { execSync } = require("child_process");
|
|
10
89
|
|
|
11
90
|
|
|
@@ -95,10 +174,10 @@ const getLatestVersionedFileName = (dir, pattern) => {
|
|
|
95
174
|
/* const requiredPlugins = [
|
|
96
175
|
|
|
97
176
|
{ pattern: /backbutton-(\d+\.\d+)\.js$/, minVersion: '2.0', required: true, baseDir: 'js',mandatoryUpdate: true},
|
|
98
|
-
|
|
177
|
+
|
|
99
178
|
|
|
100
179
|
{ pattern: /common-(\d+\.\d+)(?:-beta-(\d+))?\.js$/, minVersion: '6.0', required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
101
|
-
|
|
180
|
+
|
|
102
181
|
{ pattern: /localization_settings-(\d+\.\d+)\.js$/, minVersion: '1.1', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
103
182
|
{ pattern: /localization-(\d+\.\d+)\.js$/, minVersion: '1.5', required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
104
183
|
{ pattern: /localNotification-(\d+\.\d+)\.js$/, minVersion: '2.2', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
@@ -110,8 +189,8 @@ const getLatestVersionedFileName = (dir, pattern) => {
|
|
|
110
189
|
{ pattern: /video-player-(\d+\.\d+)\.js$/, minVersion: '1.5', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
111
190
|
{ pattern: /image-cropper-(\d+\.\d+)\.js$/, minVersion: '1.1', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
112
191
|
{ pattern: /common-(\d+\.\d+)\.less$/, minVersion: '1.6', required: true, baseDir: 'assets/css',mandatoryUpdate: false },
|
|
113
|
-
|
|
114
|
-
|
|
192
|
+
|
|
193
|
+
|
|
115
194
|
// New folders
|
|
116
195
|
{ pattern: /IAP-(\d+\.\d+)$/, minVersion: '2.8', isFolder: true , required: true, baseDir: 'js/Ads',mandatoryUpdate: true },
|
|
117
196
|
{ pattern: /editor-(\d+\.\d+)$/, minVersion: '1.9', isFolder: true, required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
@@ -120,11 +199,11 @@ const getLatestVersionedFileName = (dir, pattern) => {
|
|
|
120
199
|
|
|
121
200
|
|
|
122
201
|
{ pattern: /certificatejs-(\d+\.\d+)$/, minVersion: '1.6', isFolder: true , required: true, baseDir: 'certificate',mandatoryUpdate: true }
|
|
123
|
-
|
|
202
|
+
|
|
124
203
|
]; */
|
|
125
204
|
|
|
126
205
|
|
|
127
|
-
const ROOT_DIR = path.join(
|
|
206
|
+
const ROOT_DIR = path.join(process.cwd(), "src");
|
|
128
207
|
|
|
129
208
|
function requireOrInstall(packageName) {
|
|
130
209
|
try {
|
|
@@ -230,6 +309,7 @@ function loadRequiredPlugins() {
|
|
|
230
309
|
!/^admob-(?:emi-)?nextgen$/i.test(String(p.name || '')) && !/^onesignal(?:-|$)/i.test(String(p.name || '')) && !/onesignal/i.test(String(p.pattern || ''))
|
|
231
310
|
).map(p => ({
|
|
232
311
|
...p,
|
|
312
|
+
minVersion: p.name === 'IAP' && compareVersionStrings(p.minVersion, '4.6') < 0 ? '4.6' : p.minVersion,
|
|
233
313
|
pattern: new RegExp(p.pattern)
|
|
234
314
|
}));
|
|
235
315
|
|
|
@@ -289,6 +369,12 @@ function getLatestVersion(packageName) {
|
|
|
289
369
|
|
|
290
370
|
function checkPackageVersion() {
|
|
291
371
|
const packageName = 'codeplay-common';
|
|
372
|
+
const appPackage = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
373
|
+
const declaredPackage = appPackage.dependencies?.[packageName] || appPackage.devDependencies?.[packageName] || '';
|
|
374
|
+
if (/^(?:file:|link:|workspace:)/.test(declaredPackage)) {
|
|
375
|
+
console.log('Using local codeplay-common source; skipping registry replacement.');
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
292
378
|
const installedVersion = getInstalledVersion(packageName);
|
|
293
379
|
const latestVersion = getLatestVersion(packageName);
|
|
294
380
|
|
|
@@ -298,9 +384,9 @@ function checkPackageVersion() {
|
|
|
298
384
|
return;
|
|
299
385
|
}
|
|
300
386
|
|
|
301
|
-
if (installedVersion
|
|
387
|
+
if (compareVersionStrings(installedVersion, latestVersion) < 0) {
|
|
302
388
|
console.log(`${packageName} is outdated (installed: ${installedVersion}, latest: ${latestVersion}). Updating now...`);
|
|
303
|
-
|
|
389
|
+
|
|
304
390
|
try {
|
|
305
391
|
execSync(`npm uninstall ${packageName}`, { stdio: 'inherit' });
|
|
306
392
|
execSync(`npm install ${packageName}`, { stdio: 'inherit' });
|
|
@@ -424,7 +510,7 @@ const checkAppUniqueId=()=>{
|
|
|
424
510
|
|
|
425
511
|
if (!orientation) {
|
|
426
512
|
logErrorMessage+='❌ Missing android.ORIENTATION option in capacitor.config.json.\n';
|
|
427
|
-
}
|
|
513
|
+
}
|
|
428
514
|
|
|
429
515
|
else if(orientation!="portrait" && orientation!="landscape" && orientation!="auto")
|
|
430
516
|
{
|
|
@@ -555,34 +641,19 @@ const getRelativeModuleImport = (sourceFile, targetFile) => {
|
|
|
555
641
|
return relativePath;
|
|
556
642
|
};
|
|
557
643
|
|
|
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
644
|
const ensureIapStartupOnHomePage = () => {
|
|
585
645
|
const iapConfig = getAdmobIapConfig()?.IAP;
|
|
646
|
+
const visibilityHome = getHomePagePath();
|
|
647
|
+
const visibilityIap = getLatestIapDir();
|
|
648
|
+
const statePath = visibilityIap && path.join(visibilityIap, 'IAP-state.js');
|
|
649
|
+
if (visibilityHome) {
|
|
650
|
+
const original = fs.readFileSync(visibilityHome, 'utf8');
|
|
651
|
+
const next = migrateHomeIapVisibility(original, statePath && fs.existsSync(statePath) ? getRelativeModuleImport(visibilityHome, statePath) : null);
|
|
652
|
+
if (next !== original) {
|
|
653
|
+
fs.writeFileSync(visibilityHome, next, 'utf8');
|
|
654
|
+
console.log(`✅ Updated shared Pro-button visibility in ${path.relative(process.cwd(), visibilityHome)}.`);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
586
657
|
if (!isAnyIapStoreEnabled(iapConfig)) {
|
|
587
658
|
console.log("ℹ️ IAP is disabled for every store. AdMob will use direct startup.");
|
|
588
659
|
return;
|
|
@@ -605,26 +676,15 @@ const ensureIapStartupOnHomePage = () => {
|
|
|
605
676
|
|
|
606
677
|
let content = fs.readFileSync(homePagePath, "utf8");
|
|
607
678
|
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);
|
|
679
|
+
const bootstrapPath = path.join(latestIapDir, 'IAP-bootstrap.js');
|
|
680
|
+
if (!fs.existsSync(bootstrapPath)) throw new Error('IAP 4.6 or newer is required for deferred startup.');
|
|
681
|
+
content = migrateIapStartup(content, getRelativeModuleImport(homePagePath, bootstrapPath));
|
|
622
682
|
|
|
623
683
|
if (content !== originalContent) {
|
|
624
684
|
fs.writeFileSync(homePagePath, content, "utf8");
|
|
625
|
-
console.log(`✅ Added
|
|
685
|
+
console.log(`✅ Added background IAP startup to ${path.relative(process.cwd(), homePagePath)}.`);
|
|
626
686
|
} else {
|
|
627
|
-
console.log(`ℹ️
|
|
687
|
+
console.log(`ℹ️ Background IAP startup already configured in ${path.relative(process.cwd(), homePagePath)}.`);
|
|
628
688
|
}
|
|
629
689
|
};
|
|
630
690
|
|
|
@@ -647,7 +707,7 @@ const ensureIapStartupOnHomePage = () => {
|
|
|
647
707
|
//const path = require("path");
|
|
648
708
|
//const { execSync } = require("child_process");
|
|
649
709
|
|
|
650
|
-
const jsDir = path.join(
|
|
710
|
+
const jsDir = path.join(process.cwd(), "src", "js");
|
|
651
711
|
|
|
652
712
|
// 🔍 Detect OLD structure
|
|
653
713
|
const oldEditorDirs = fs.readdirSync(jsDir)
|
|
@@ -792,9 +852,9 @@ else {
|
|
|
792
852
|
|
|
793
853
|
const saveToGalleryAndSaveFileCheck_iOS = async () => {
|
|
794
854
|
|
|
795
|
-
const SOURCE_ROOT = path.resolve(
|
|
855
|
+
const SOURCE_ROOT = path.resolve(process.cwd(), 'src');
|
|
796
856
|
const EXCLUDED_DIR = path.join(SOURCE_ROOT, 'js', 'Ads');
|
|
797
|
-
const ANDROID_MANIFEST_PATH = path.resolve(
|
|
857
|
+
const ANDROID_MANIFEST_PATH = path.resolve(process.cwd(), 'android/app/src/main/AndroidManifest.xml');
|
|
798
858
|
|
|
799
859
|
|
|
800
860
|
// Skip comments and unrelated strings; match static/dynamic imports, re-exports and require.
|
|
@@ -816,7 +876,7 @@ You are using a direct version-based path like: editor/editor-x.x/editor.js
|
|
|
816
876
|
|
|
817
877
|
👉 Please use the proper alias or updated import method.
|
|
818
878
|
Example: import { ... } from '@editor'
|
|
819
|
-
|
|
879
|
+
|
|
820
880
|
⚠️ Do not use version-based paths in imports.
|
|
821
881
|
👉 Please add this manually in vite.config.js:
|
|
822
882
|
|
|
@@ -838,7 +898,7 @@ const SKIP_FILES = [
|
|
|
838
898
|
|
|
839
899
|
|
|
840
900
|
|
|
841
|
-
const STATUSBAR_FILE = path.resolve(
|
|
901
|
+
const STATUSBAR_FILE = path.resolve(process.cwd(), 'src/js/common-configuration.js');
|
|
842
902
|
const STATUSBAR_REGEX = /^(?!\s*\/\/).*Capacitor\.Plugins\.StatusBar\.setStyle/m;
|
|
843
903
|
|
|
844
904
|
|
|
@@ -1151,7 +1211,7 @@ const routes = [
|
|
|
1151
1211
|
},
|
|
1152
1212
|
}]
|
|
1153
1213
|
`);
|
|
1154
|
-
|
|
1214
|
+
|
|
1155
1215
|
badImports.forEach(({ line, number }) => {
|
|
1156
1216
|
console.error(`${number}: ${line}`);
|
|
1157
1217
|
});
|
|
@@ -1394,8 +1454,8 @@ if (updated) {
|
|
|
1394
1454
|
|
|
1395
1455
|
// Build the path dynamically like you requested
|
|
1396
1456
|
const gradlePath = path.join(
|
|
1397
|
-
process.cwd(),
|
|
1398
|
-
'android',
|
|
1457
|
+
process.cwd(),
|
|
1458
|
+
'android',
|
|
1399
1459
|
'build.gradle'
|
|
1400
1460
|
);
|
|
1401
1461
|
|
|
@@ -1614,11 +1674,11 @@ function validateAndroidBuildOptions() {
|
|
|
1614
1674
|
const targetAppId=config.appId
|
|
1615
1675
|
|
|
1616
1676
|
const buildOptions = config.android?.buildOptions;
|
|
1617
|
-
|
|
1677
|
+
|
|
1618
1678
|
if (!buildOptions) {
|
|
1619
1679
|
console.log('❌ Missing android.buildOptions in capacitor.config.json.');
|
|
1620
1680
|
process.exit(1);
|
|
1621
|
-
}
|
|
1681
|
+
}
|
|
1622
1682
|
|
|
1623
1683
|
const requiredProps = [
|
|
1624
1684
|
'keystorePath',
|
|
@@ -1630,13 +1690,13 @@ function validateAndroidBuildOptions() {
|
|
|
1630
1690
|
];
|
|
1631
1691
|
|
|
1632
1692
|
const missing = requiredProps.filter(prop => !buildOptions[prop]);
|
|
1633
|
-
|
|
1693
|
+
|
|
1634
1694
|
if (missing.length > 0) {
|
|
1635
1695
|
console.log('❌ Missing properties android.buildOptions in capacitor.config.json.');
|
|
1636
1696
|
process.exit(1);
|
|
1637
1697
|
}
|
|
1638
1698
|
|
|
1639
|
-
|
|
1699
|
+
|
|
1640
1700
|
const keystorePath=buildOptions.keystorePath
|
|
1641
1701
|
const keyFileName = path.basename(keystorePath);
|
|
1642
1702
|
|
|
@@ -1826,7 +1886,7 @@ try {
|
|
|
1826
1886
|
_admobConfig = getAdMobConfig();
|
|
1827
1887
|
|
|
1828
1888
|
|
|
1829
|
-
|
|
1889
|
+
|
|
1830
1890
|
|
|
1831
1891
|
|
|
1832
1892
|
// Proceed only if ADMOB_ENABLED is true
|
|
@@ -2170,7 +2230,9 @@ async function syncAgentInstructions() {
|
|
|
2170
2230
|
|
|
2171
2231
|
const zipName = `${AGENT_INSTRUCTIONS_ZIP_PREFIX}-${remoteVersion}.zip`;
|
|
2172
2232
|
const url = `https://htmlcodeplay.com/code-play-plugin/${zipName}`;
|
|
2173
|
-
const
|
|
2233
|
+
const agentTempRoot = path.join(process.cwd(), "agent-temp", "agent-instructions");
|
|
2234
|
+
fs.mkdirSync(agentTempRoot, { recursive: true });
|
|
2235
|
+
const tempRoot = fs.mkdtempSync(path.join(agentTempRoot, "codeplay-agents-"));
|
|
2174
2236
|
const zipPath = path.join(tempRoot, zipName);
|
|
2175
2237
|
const extractPath = path.join(tempRoot, "extracted");
|
|
2176
2238
|
|
|
@@ -2248,7 +2310,9 @@ if (baseName === "common") {
|
|
|
2248
2310
|
if (ext === ".less") pluginKey = "common-less";
|
|
2249
2311
|
}
|
|
2250
2312
|
|
|
2251
|
-
const
|
|
2313
|
+
const advertisedVersion = versions[pluginKey];
|
|
2314
|
+
const latestVersion = baseName === 'IAP' && (!advertisedVersion || compareVersionStrings(advertisedVersion, pluginDef.minVersion) < 0)
|
|
2315
|
+
? pluginDef.minVersion : advertisedVersion;
|
|
2252
2316
|
|
|
2253
2317
|
if (!latestVersion) {
|
|
2254
2318
|
console.log(`❌ No version entry for ${baseName}`);
|
|
@@ -2269,12 +2333,17 @@ if (pluginDef.isFolder) {
|
|
|
2269
2333
|
|
|
2270
2334
|
if (!(await urlExists(url))) return false;
|
|
2271
2335
|
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2336
|
+
const stagingRoot = path.join(process.cwd(), 'agent-temp', 'iap-package-sync');
|
|
2337
|
+
fs.mkdirSync(stagingRoot, { recursive: true });
|
|
2338
|
+
const staging = fs.mkdtempSync(path.join(stagingRoot, 'package-'));
|
|
2339
|
+
await downloadAndExtractZip(url, staging);
|
|
2340
|
+
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');
|
|
2341
|
+
if (fs.existsSync(newPath)) throw new Error('Replacement folder already exists; existing sources preserved.');
|
|
2342
|
+
fs.renameSync(staging, newPath);
|
|
2343
|
+
sourceFileInventory = null;
|
|
2276
2344
|
updateImports(pluginInfo.name, `${baseName}-${latestVersion}`);
|
|
2277
2345
|
|
|
2346
|
+
fs.rmSync(oldPath, { recursive: true, force: true });
|
|
2278
2347
|
// ✅ ADD THIS
|
|
2279
2348
|
writeUpdateLine(`${pluginInfo.name} -> ${baseName}-${latestVersion}`);
|
|
2280
2349
|
|
|
@@ -2352,7 +2421,7 @@ existingFiles.forEach(file => {
|
|
|
2352
2421
|
fs.unlinkSync(oldPath);
|
|
2353
2422
|
|
|
2354
2423
|
console.log(`🗑 Removed old file → ${file}`);
|
|
2355
|
-
//writeUpdateLine(`Removed old file: ${file}`);
|
|
2424
|
+
//writeUpdateLine(`Removed old file: ${file}`);
|
|
2356
2425
|
}
|
|
2357
2426
|
|
|
2358
2427
|
});
|
|
@@ -2415,7 +2484,7 @@ async function loadPluginVersions() {
|
|
|
2415
2484
|
if (!plugin.name) return;
|
|
2416
2485
|
|
|
2417
2486
|
if (versions[plugin.name]) {
|
|
2418
|
-
plugin.minVersion = versions[plugin.name];
|
|
2487
|
+
if (compareVersionStrings(versions[plugin.name], plugin.minVersion) > 0) plugin.minVersion = versions[plugin.name];
|
|
2419
2488
|
}
|
|
2420
2489
|
|
|
2421
2490
|
});
|
|
@@ -2518,7 +2587,7 @@ function checkPlugins() {
|
|
|
2518
2587
|
} */
|
|
2519
2588
|
|
|
2520
2589
|
|
|
2521
|
-
|
|
2590
|
+
|
|
2522
2591
|
|
|
2523
2592
|
|
|
2524
2593
|
if (hasMandatoryUpdate) {
|
|
@@ -2625,14 +2694,14 @@ if (hasMandatoryUpdate) {
|
|
|
2625
2694
|
|
|
2626
2695
|
|
|
2627
2696
|
|
|
2628
|
-
const localizationBaseDir = path.join(
|
|
2697
|
+
const localizationBaseDir = path.join(process.cwd(), "src", "js", "localization");
|
|
2629
2698
|
|
|
2630
2699
|
// ======================================================
|
|
2631
2700
|
// 🌐 LOCALIZATION CHECK (FULLY DYNAMIC)
|
|
2632
2701
|
// ======================================================
|
|
2633
2702
|
|
|
2634
2703
|
|
|
2635
|
-
const jsRootDir = path.join(
|
|
2704
|
+
const jsRootDir = path.join(process.cwd(), "src", "js");
|
|
2636
2705
|
|
|
2637
2706
|
// 🔍 Detect OLD localization files in root js/
|
|
2638
2707
|
const oldLocalizationFiles = fs.readdirSync(jsRootDir)
|
|
@@ -2876,6 +2945,17 @@ function getViteConfigPath() {
|
|
|
2876
2945
|
.find(filePath => fs.existsSync(filePath));
|
|
2877
2946
|
};
|
|
2878
2947
|
|
|
2948
|
+
const syncViteTreeShaking = () => {
|
|
2949
|
+
const configPath = getViteConfigPath();
|
|
2950
|
+
if (!configPath) return;
|
|
2951
|
+
const current = fs.readFileSync(configPath, 'utf8');
|
|
2952
|
+
const next = migrateViteTreeShaking(current);
|
|
2953
|
+
if (next !== current) {
|
|
2954
|
+
fs.writeFileSync(configPath, next, 'utf8');
|
|
2955
|
+
console.log('✅ Enabled Vite tree shaking for common JavaScript and other unused exports.');
|
|
2956
|
+
}
|
|
2957
|
+
};
|
|
2958
|
+
|
|
2879
2959
|
const getLatestIapDir = () => {
|
|
2880
2960
|
const adsDir = path.join(process.cwd(), "src", "js", "Ads");
|
|
2881
2961
|
|
|
@@ -3713,6 +3793,7 @@ const ensureIapDesignInCapacitorConfig = (iapConfig) => {
|
|
|
3713
3793
|
};
|
|
3714
3794
|
|
|
3715
3795
|
const getCurrentStoreId = () => {
|
|
3796
|
+
if (buildPlatform === 'ios') return 6;
|
|
3716
3797
|
const envStoreId = Number(process.env.VITE_STORE_ID);
|
|
3717
3798
|
if (Number.isInteger(envStoreId) && envStoreId > 0) return envStoreId;
|
|
3718
3799
|
|
|
@@ -3900,6 +3981,17 @@ const syncRevenueCatIapSetup = () => {
|
|
|
3900
3981
|
console.log(`ℹ️ RevenueCat package is not required for store id ${storeId}.`);
|
|
3901
3982
|
}
|
|
3902
3983
|
|
|
3984
|
+
const samsungEnabled = storeId === 2 && iapConfig.samsung === true;
|
|
3985
|
+
const samsungPackagePath = path.join(process.cwd(), 'node_modules', 'cordova-plugin-samsungiap', 'package.json');
|
|
3986
|
+
const samsungVersion = fs.existsSync(samsungPackagePath) ? JSON.parse(fs.readFileSync(samsungPackagePath, 'utf8')).version : '0';
|
|
3987
|
+
if (samsungEnabled && (!isPackageAvailable('cordova-plugin-samsungiap') || compareVersionStrings(samsungVersion, '2.0.0') < 0)) {
|
|
3988
|
+
runNpmCommand('npm install cordova-plugin-samsungiap@^2.0.0');
|
|
3989
|
+
packageChanged = true;
|
|
3990
|
+
} else if (!samsungEnabled && isPackageAvailable('cordova-plugin-samsungiap')) {
|
|
3991
|
+
runNpmCommand('npm uninstall cordova-plugin-samsungiap');
|
|
3992
|
+
packageChanged = true;
|
|
3993
|
+
}
|
|
3994
|
+
ensureAndroidPermission('com.samsung.android.iap.permission.BILLING', samsungEnabled);
|
|
3903
3995
|
ensureAndroidPermission("com.android.vending.BILLING", store?.usesGoogleBilling === true && revenueCatEnabledForCurrentStore);
|
|
3904
3996
|
|
|
3905
3997
|
if (iapConfig.samsung === true && revenueCatEnabled) {
|
|
@@ -4169,8 +4261,8 @@ const validateAndRestoreSignDetails=()=>{
|
|
|
4169
4261
|
|
|
4170
4262
|
|
|
4171
4263
|
const filePath = path.join(
|
|
4172
|
-
|
|
4173
|
-
"
|
|
4264
|
+
process.cwd(),
|
|
4265
|
+
"node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java"
|
|
4174
4266
|
);
|
|
4175
4267
|
|
|
4176
4268
|
const SYSTEM_BARS_PATCH_MARKER = "CODEPLAY_KEYBOARD_INSET_FIX";
|
|
@@ -4388,21 +4480,28 @@ function syncAndroidCordovaResourceKeep() {
|
|
|
4388
4480
|
}
|
|
4389
4481
|
|
|
4390
4482
|
async function main() {
|
|
4483
|
+
const buildPackage = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
4484
|
+
const buildScripts = updateBuildEntrypoints(buildPackage.scripts || {});
|
|
4485
|
+
if (JSON.stringify(buildScripts) !== JSON.stringify(buildPackage.scripts)) {
|
|
4486
|
+
buildPackage.scripts = buildScripts;
|
|
4487
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(buildPackage, null, 2) + '\n');
|
|
4488
|
+
}
|
|
4391
4489
|
validateThemeFolderLocation();
|
|
4392
4490
|
validateAndRestoreSignDetails();
|
|
4393
4491
|
ensureMandatoryCapacitorPlugins();
|
|
4394
4492
|
|
|
4395
4493
|
await loadPluginVersions(); // 🔥 NEW
|
|
4396
4494
|
await syncAgentInstructions();
|
|
4495
|
+
await checkPlugins();
|
|
4397
4496
|
|
|
4398
4497
|
await syncAdmobNextgenMigration();
|
|
4399
4498
|
syncCodeplaySystemBarsPackage();
|
|
4400
4499
|
syncSystemBarsSafeAreaMigration();
|
|
4401
|
-
await checkPlugins();
|
|
4402
4500
|
ensureIapStartupOnHomePage();
|
|
4403
4501
|
syncRevenueCatIapSetup();
|
|
4404
4502
|
syncFirebaseAnalyticsSetup();
|
|
4405
4503
|
checkAndupdateDropInViteConfig();
|
|
4504
|
+
syncViteTreeShaking();
|
|
4406
4505
|
checkAdmobConfigurationProperty();
|
|
4407
4506
|
syncAndroidAdIdPermission();
|
|
4408
4507
|
syncAndroidBuildOptimization();
|