codeplay-common 4.9.7 → 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 +31 -1
- package/README.md +48 -2
- package/RELEASE_NOTES.md +31 -1
- 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.4.js → codeplayBeforeBuild.js} +169 -165
- 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 +218 -0
- package/files/buildCodeplay/versions.json +2 -2
- package/files/finalrelease +1233 -1360
- package/files/take-screen-image.js +2 -2
- package/package.json +16 -4
- package/scripts/sync-files.js +79 -103
- package/scripts/uninstall.js +3 -123
- package/.gitattributes +0 -2
- 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,10 +1,83 @@
|
|
|
1
|
-
// 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.
|
|
2
4
|
const fs = require('fs');
|
|
3
5
|
const path = require('path');
|
|
4
6
|
const plist = require('plist');
|
|
5
7
|
|
|
6
8
|
|
|
7
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
|
+
|
|
8
81
|
const { execSync } = require("child_process");
|
|
9
82
|
|
|
10
83
|
|
|
@@ -42,8 +115,7 @@ const configPath = path.join(process.cwd(), 'capacitor.config.json');
|
|
|
42
115
|
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
43
116
|
const updateLogFile = path.join(process.cwd(), "", "plugin-update-log.txt");
|
|
44
117
|
const ONESIGNAL_PLUGIN_NAME = "onesignal-cordova-plugin";
|
|
45
|
-
const
|
|
46
|
-
const ADMOB_NEXTGEN_FILE_PATTERN = new RegExp(`^${ADMOB_NEXTGEN_PLUGIN_NAME}-\\d+(?:\\.\\d+)*\\.js$`);
|
|
118
|
+
const { syncAdmobNextgen, syncImports: syncAdmobImports, findLatestPackage: findAdmobPackage } = require('./sync-admob-nextgen.js');
|
|
47
119
|
const ADMOB_NEXTGEN_CONFIG = "admob-ad-configuration-nextgen.json";
|
|
48
120
|
const ADMOB_OLD_CONFIG = "admob-ad-configuration.json";
|
|
49
121
|
const AGENT_INSTRUCTIONS_VERSION_KEY = "agents";
|
|
@@ -90,17 +162,15 @@ const getLatestVersionedFileName = (dir, pattern) => {
|
|
|
90
162
|
})[0];
|
|
91
163
|
};
|
|
92
164
|
|
|
93
|
-
const getLatestAdmobNextgenFileName = (adsDir) =>
|
|
94
|
-
getLatestVersionedFileName(adsDir, ADMOB_NEXTGEN_FILE_PATTERN);
|
|
95
165
|
|
|
96
166
|
// Expected plugin list with minimum versions
|
|
97
167
|
/* const requiredPlugins = [
|
|
98
168
|
|
|
99
169
|
{ pattern: /backbutton-(\d+\.\d+)\.js$/, minVersion: '2.0', required: true, baseDir: 'js',mandatoryUpdate: true},
|
|
100
|
-
|
|
170
|
+
|
|
101
171
|
|
|
102
172
|
{ pattern: /common-(\d+\.\d+)(?:-beta-(\d+))?\.js$/, minVersion: '6.0', required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
103
|
-
|
|
173
|
+
|
|
104
174
|
{ pattern: /localization_settings-(\d+\.\d+)\.js$/, minVersion: '1.1', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
105
175
|
{ pattern: /localization-(\d+\.\d+)\.js$/, minVersion: '1.5', required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
106
176
|
{ pattern: /localNotification-(\d+\.\d+)\.js$/, minVersion: '2.2', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
@@ -112,8 +182,8 @@ const getLatestAdmobNextgenFileName = (adsDir) =>
|
|
|
112
182
|
{ pattern: /video-player-(\d+\.\d+)\.js$/, minVersion: '1.5', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
113
183
|
{ pattern: /image-cropper-(\d+\.\d+)\.js$/, minVersion: '1.1', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
114
184
|
{ pattern: /common-(\d+\.\d+)\.less$/, minVersion: '1.6', required: true, baseDir: 'assets/css',mandatoryUpdate: false },
|
|
115
|
-
|
|
116
|
-
|
|
185
|
+
|
|
186
|
+
|
|
117
187
|
// New folders
|
|
118
188
|
{ pattern: /IAP-(\d+\.\d+)$/, minVersion: '2.8', isFolder: true , required: true, baseDir: 'js/Ads',mandatoryUpdate: true },
|
|
119
189
|
{ pattern: /editor-(\d+\.\d+)$/, minVersion: '1.9', isFolder: true, required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
@@ -122,11 +192,11 @@ const getLatestAdmobNextgenFileName = (adsDir) =>
|
|
|
122
192
|
|
|
123
193
|
|
|
124
194
|
{ pattern: /certificatejs-(\d+\.\d+)$/, minVersion: '1.6', isFolder: true , required: true, baseDir: 'certificate',mandatoryUpdate: true }
|
|
125
|
-
|
|
195
|
+
|
|
126
196
|
]; */
|
|
127
197
|
|
|
128
198
|
|
|
129
|
-
const ROOT_DIR = path.join(
|
|
199
|
+
const ROOT_DIR = path.join(process.cwd(), "src");
|
|
130
200
|
|
|
131
201
|
function requireOrInstall(packageName) {
|
|
132
202
|
try {
|
|
@@ -229,9 +299,10 @@ function loadRequiredPlugins() {
|
|
|
229
299
|
|
|
230
300
|
// OneSignal is retired; do not download its legacy helpers again.
|
|
231
301
|
return json.plugins.filter(p =>
|
|
232
|
-
!/^onesignal(?:-|$)/i.test(String(p.name || '')) && !/onesignal/i.test(String(p.pattern || ''))
|
|
302
|
+
!/^admob-(?:emi-)?nextgen$/i.test(String(p.name || '')) && !/^onesignal(?:-|$)/i.test(String(p.name || '')) && !/onesignal/i.test(String(p.pattern || ''))
|
|
233
303
|
).map(p => ({
|
|
234
304
|
...p,
|
|
305
|
+
minVersion: p.name === 'IAP' && compareVersionStrings(p.minVersion, '4.6') < 0 ? '4.6' : p.minVersion,
|
|
235
306
|
pattern: new RegExp(p.pattern)
|
|
236
307
|
}));
|
|
237
308
|
|
|
@@ -291,6 +362,12 @@ function getLatestVersion(packageName) {
|
|
|
291
362
|
|
|
292
363
|
function checkPackageVersion() {
|
|
293
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
|
+
}
|
|
294
371
|
const installedVersion = getInstalledVersion(packageName);
|
|
295
372
|
const latestVersion = getLatestVersion(packageName);
|
|
296
373
|
|
|
@@ -300,9 +377,9 @@ function checkPackageVersion() {
|
|
|
300
377
|
return;
|
|
301
378
|
}
|
|
302
379
|
|
|
303
|
-
if (installedVersion
|
|
380
|
+
if (compareVersionStrings(installedVersion, latestVersion) < 0) {
|
|
304
381
|
console.log(`${packageName} is outdated (installed: ${installedVersion}, latest: ${latestVersion}). Updating now...`);
|
|
305
|
-
|
|
382
|
+
|
|
306
383
|
try {
|
|
307
384
|
execSync(`npm uninstall ${packageName}`, { stdio: 'inherit' });
|
|
308
385
|
execSync(`npm install ${packageName}`, { stdio: 'inherit' });
|
|
@@ -426,7 +503,7 @@ const checkAppUniqueId=()=>{
|
|
|
426
503
|
|
|
427
504
|
if (!orientation) {
|
|
428
505
|
logErrorMessage+='❌ Missing android.ORIENTATION option in capacitor.config.json.\n';
|
|
429
|
-
}
|
|
506
|
+
}
|
|
430
507
|
|
|
431
508
|
else if(orientation!="portrait" && orientation!="landscape" && orientation!="auto")
|
|
432
509
|
{
|
|
@@ -557,34 +634,19 @@ const getRelativeModuleImport = (sourceFile, targetFile) => {
|
|
|
557
634
|
return relativePath;
|
|
558
635
|
};
|
|
559
636
|
|
|
560
|
-
const addInitIapToExistingImport = (content) => {
|
|
561
|
-
const iapImportRegex = /import\s*\{([^}]*)\}\s*from\s*(['"])([^'"]*\/IAP-\d+(?:\.\d+)*\/IAP-check-And-LoadAd\.js)\2\s*;?/;
|
|
562
|
-
const match = content.match(iapImportRegex);
|
|
563
|
-
if (!match || /\binitIAP\b/.test(match[1])) return content;
|
|
564
|
-
|
|
565
|
-
const importNames = match[1].trim();
|
|
566
|
-
const nextImportNames = importNames ? `initIAP, ${importNames}` : "initIAP";
|
|
567
|
-
return content.replace(iapImportRegex, `import { ${nextImportNames} } from ${match[2]}${match[3]}${match[2]};`);
|
|
568
|
-
};
|
|
569
|
-
|
|
570
|
-
const addInitIapCall = (content) => {
|
|
571
|
-
if (/\binitIAP\s*\(/.test(content)) return content;
|
|
572
|
-
|
|
573
|
-
const pageInitRegex = /(\$on\(\s*(['"])pageInit\2\s*,\s*(?:async\s*)?\(\)\s*=>\s*\{\s*\r?\n)/;
|
|
574
|
-
if (pageInitRegex.test(content)) {
|
|
575
|
-
return content.replace(pageInitRegex, "$1 initIAP();\n");
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
const componentStartRegex = /(export\s+default\s*\([^)]*\)\s*=>\s*\{\s*\r?\n)/;
|
|
579
|
-
if (componentStartRegex.test(content)) {
|
|
580
|
-
return content.replace(componentStartRegex, "$1 initIAP();\n");
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
throw new Error("Unable to find a Framework7 component or pageInit lifecycle for IAP startup.");
|
|
584
|
-
};
|
|
585
|
-
|
|
586
637
|
const ensureIapStartupOnHomePage = () => {
|
|
587
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
|
+
}
|
|
588
650
|
if (!isAnyIapStoreEnabled(iapConfig)) {
|
|
589
651
|
console.log("ℹ️ IAP is disabled for every store. AdMob will use direct startup.");
|
|
590
652
|
return;
|
|
@@ -607,26 +669,15 @@ const ensureIapStartupOnHomePage = () => {
|
|
|
607
669
|
|
|
608
670
|
let content = fs.readFileSync(homePagePath, "utf8");
|
|
609
671
|
const originalContent = content;
|
|
610
|
-
const
|
|
611
|
-
|
|
612
|
-
content =
|
|
613
|
-
|
|
614
|
-
if (!staticInitImportRegex.test(content)) {
|
|
615
|
-
const relativeImport = getRelativeModuleImport(homePagePath, iapModulePath);
|
|
616
|
-
const scriptStartRegex = /<script>\s*\r?\n/;
|
|
617
|
-
if (!scriptStartRegex.test(content)) {
|
|
618
|
-
throw new Error(`Unable to find the script block in ${homePagePath}`);
|
|
619
|
-
}
|
|
620
|
-
content = content.replace(scriptStartRegex, `$&import { initIAP } from '${relativeImport}';\n`);
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
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));
|
|
624
675
|
|
|
625
676
|
if (content !== originalContent) {
|
|
626
677
|
fs.writeFileSync(homePagePath, content, "utf8");
|
|
627
|
-
console.log(`✅ Added
|
|
678
|
+
console.log(`✅ Added background IAP startup to ${path.relative(process.cwd(), homePagePath)}.`);
|
|
628
679
|
} else {
|
|
629
|
-
console.log(`ℹ️
|
|
680
|
+
console.log(`ℹ️ Background IAP startup already configured in ${path.relative(process.cwd(), homePagePath)}.`);
|
|
630
681
|
}
|
|
631
682
|
};
|
|
632
683
|
|
|
@@ -649,7 +700,7 @@ const ensureIapStartupOnHomePage = () => {
|
|
|
649
700
|
//const path = require("path");
|
|
650
701
|
//const { execSync } = require("child_process");
|
|
651
702
|
|
|
652
|
-
const jsDir = path.join(
|
|
703
|
+
const jsDir = path.join(process.cwd(), "src", "js");
|
|
653
704
|
|
|
654
705
|
// 🔍 Detect OLD structure
|
|
655
706
|
const oldEditorDirs = fs.readdirSync(jsDir)
|
|
@@ -794,9 +845,9 @@ else {
|
|
|
794
845
|
|
|
795
846
|
const saveToGalleryAndSaveFileCheck_iOS = async () => {
|
|
796
847
|
|
|
797
|
-
const SOURCE_ROOT = path.resolve(
|
|
848
|
+
const SOURCE_ROOT = path.resolve(process.cwd(), 'src');
|
|
798
849
|
const EXCLUDED_DIR = path.join(SOURCE_ROOT, 'js', 'Ads');
|
|
799
|
-
const ANDROID_MANIFEST_PATH = path.resolve(
|
|
850
|
+
const ANDROID_MANIFEST_PATH = path.resolve(process.cwd(), 'android/app/src/main/AndroidManifest.xml');
|
|
800
851
|
|
|
801
852
|
|
|
802
853
|
// Skip comments and unrelated strings; match static/dynamic imports, re-exports and require.
|
|
@@ -818,7 +869,7 @@ You are using a direct version-based path like: editor/editor-x.x/editor.js
|
|
|
818
869
|
|
|
819
870
|
👉 Please use the proper alias or updated import method.
|
|
820
871
|
Example: import { ... } from '@editor'
|
|
821
|
-
|
|
872
|
+
|
|
822
873
|
⚠️ Do not use version-based paths in imports.
|
|
823
874
|
👉 Please add this manually in vite.config.js:
|
|
824
875
|
|
|
@@ -840,7 +891,7 @@ const SKIP_FILES = [
|
|
|
840
891
|
|
|
841
892
|
|
|
842
893
|
|
|
843
|
-
const STATUSBAR_FILE = path.resolve(
|
|
894
|
+
const STATUSBAR_FILE = path.resolve(process.cwd(), 'src/js/common-configuration.js');
|
|
844
895
|
const STATUSBAR_REGEX = /^(?!\s*\/\/).*Capacitor\.Plugins\.StatusBar\.setStyle/m;
|
|
845
896
|
|
|
846
897
|
|
|
@@ -1153,7 +1204,7 @@ const routes = [
|
|
|
1153
1204
|
},
|
|
1154
1205
|
}]
|
|
1155
1206
|
`);
|
|
1156
|
-
|
|
1207
|
+
|
|
1157
1208
|
badImports.forEach(({ line, number }) => {
|
|
1158
1209
|
console.error(`${number}: ${line}`);
|
|
1159
1210
|
});
|
|
@@ -1396,8 +1447,8 @@ if (updated) {
|
|
|
1396
1447
|
|
|
1397
1448
|
// Build the path dynamically like you requested
|
|
1398
1449
|
const gradlePath = path.join(
|
|
1399
|
-
process.cwd(),
|
|
1400
|
-
'android',
|
|
1450
|
+
process.cwd(),
|
|
1451
|
+
'android',
|
|
1401
1452
|
'build.gradle'
|
|
1402
1453
|
);
|
|
1403
1454
|
|
|
@@ -1616,11 +1667,11 @@ function validateAndroidBuildOptions() {
|
|
|
1616
1667
|
const targetAppId=config.appId
|
|
1617
1668
|
|
|
1618
1669
|
const buildOptions = config.android?.buildOptions;
|
|
1619
|
-
|
|
1670
|
+
|
|
1620
1671
|
if (!buildOptions) {
|
|
1621
1672
|
console.log('❌ Missing android.buildOptions in capacitor.config.json.');
|
|
1622
1673
|
process.exit(1);
|
|
1623
|
-
}
|
|
1674
|
+
}
|
|
1624
1675
|
|
|
1625
1676
|
const requiredProps = [
|
|
1626
1677
|
'keystorePath',
|
|
@@ -1632,13 +1683,13 @@ function validateAndroidBuildOptions() {
|
|
|
1632
1683
|
];
|
|
1633
1684
|
|
|
1634
1685
|
const missing = requiredProps.filter(prop => !buildOptions[prop]);
|
|
1635
|
-
|
|
1686
|
+
|
|
1636
1687
|
if (missing.length > 0) {
|
|
1637
1688
|
console.log('❌ Missing properties android.buildOptions in capacitor.config.json.');
|
|
1638
1689
|
process.exit(1);
|
|
1639
1690
|
}
|
|
1640
1691
|
|
|
1641
|
-
|
|
1692
|
+
|
|
1642
1693
|
const keystorePath=buildOptions.keystorePath
|
|
1643
1694
|
const keyFileName = path.basename(keystorePath);
|
|
1644
1695
|
|
|
@@ -1828,7 +1879,7 @@ try {
|
|
|
1828
1879
|
_admobConfig = getAdMobConfig();
|
|
1829
1880
|
|
|
1830
1881
|
|
|
1831
|
-
|
|
1882
|
+
|
|
1832
1883
|
|
|
1833
1884
|
|
|
1834
1885
|
// Proceed only if ADMOB_ENABLED is true
|
|
@@ -2172,7 +2223,9 @@ async function syncAgentInstructions() {
|
|
|
2172
2223
|
|
|
2173
2224
|
const zipName = `${AGENT_INSTRUCTIONS_ZIP_PREFIX}-${remoteVersion}.zip`;
|
|
2174
2225
|
const url = `https://htmlcodeplay.com/code-play-plugin/${zipName}`;
|
|
2175
|
-
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-"));
|
|
2176
2229
|
const zipPath = path.join(tempRoot, zipName);
|
|
2177
2230
|
const extractPath = path.join(tempRoot, "extracted");
|
|
2178
2231
|
|
|
@@ -2218,15 +2271,7 @@ async function syncAgentInstructions() {
|
|
|
2218
2271
|
|
|
2219
2272
|
|
|
2220
2273
|
|
|
2221
|
-
async function getLatestRemoteAdmobNextgenFileName() {
|
|
2222
|
-
const versions = await fetchVersions();
|
|
2223
|
-
if (!versions || typeof versions !== "object") return null;
|
|
2224
|
-
|
|
2225
|
-
const remoteVersion = String(versions[ADMOB_NEXTGEN_PLUGIN_NAME] || "").trim();
|
|
2226
|
-
if (!/^\d+(?:\.\d+)*$/.test(remoteVersion)) return null;
|
|
2227
2274
|
|
|
2228
|
-
return `${ADMOB_NEXTGEN_PLUGIN_NAME}-${remoteVersion}.js`;
|
|
2229
|
-
}
|
|
2230
2275
|
|
|
2231
2276
|
async function autoUpdatePlugin(pluginDef, pluginInfo) {
|
|
2232
2277
|
|
|
@@ -2258,7 +2303,9 @@ if (baseName === "common") {
|
|
|
2258
2303
|
if (ext === ".less") pluginKey = "common-less";
|
|
2259
2304
|
}
|
|
2260
2305
|
|
|
2261
|
-
const
|
|
2306
|
+
const advertisedVersion = versions[pluginKey];
|
|
2307
|
+
const latestVersion = baseName === 'IAP' && (!advertisedVersion || compareVersionStrings(advertisedVersion, pluginDef.minVersion) < 0)
|
|
2308
|
+
? pluginDef.minVersion : advertisedVersion;
|
|
2262
2309
|
|
|
2263
2310
|
if (!latestVersion) {
|
|
2264
2311
|
console.log(`❌ No version entry for ${baseName}`);
|
|
@@ -2279,12 +2326,17 @@ if (pluginDef.isFolder) {
|
|
|
2279
2326
|
|
|
2280
2327
|
if (!(await urlExists(url))) return false;
|
|
2281
2328
|
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
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;
|
|
2286
2337
|
updateImports(pluginInfo.name, `${baseName}-${latestVersion}`);
|
|
2287
2338
|
|
|
2339
|
+
fs.rmSync(oldPath, { recursive: true, force: true });
|
|
2288
2340
|
// ✅ ADD THIS
|
|
2289
2341
|
writeUpdateLine(`${pluginInfo.name} -> ${baseName}-${latestVersion}`);
|
|
2290
2342
|
|
|
@@ -2362,7 +2414,7 @@ existingFiles.forEach(file => {
|
|
|
2362
2414
|
fs.unlinkSync(oldPath);
|
|
2363
2415
|
|
|
2364
2416
|
console.log(`🗑 Removed old file → ${file}`);
|
|
2365
|
-
//writeUpdateLine(`Removed old file: ${file}`);
|
|
2417
|
+
//writeUpdateLine(`Removed old file: ${file}`);
|
|
2366
2418
|
}
|
|
2367
2419
|
|
|
2368
2420
|
});
|
|
@@ -2425,7 +2477,7 @@ async function loadPluginVersions() {
|
|
|
2425
2477
|
if (!plugin.name) return;
|
|
2426
2478
|
|
|
2427
2479
|
if (versions[plugin.name]) {
|
|
2428
|
-
plugin.minVersion = versions[plugin.name];
|
|
2480
|
+
if (compareVersionStrings(versions[plugin.name], plugin.minVersion) > 0) plugin.minVersion = versions[plugin.name];
|
|
2429
2481
|
}
|
|
2430
2482
|
|
|
2431
2483
|
});
|
|
@@ -2528,7 +2580,7 @@ function checkPlugins() {
|
|
|
2528
2580
|
} */
|
|
2529
2581
|
|
|
2530
2582
|
|
|
2531
|
-
|
|
2583
|
+
|
|
2532
2584
|
|
|
2533
2585
|
|
|
2534
2586
|
if (hasMandatoryUpdate) {
|
|
@@ -2635,14 +2687,14 @@ if (hasMandatoryUpdate) {
|
|
|
2635
2687
|
|
|
2636
2688
|
|
|
2637
2689
|
|
|
2638
|
-
const localizationBaseDir = path.join(
|
|
2690
|
+
const localizationBaseDir = path.join(process.cwd(), "src", "js", "localization");
|
|
2639
2691
|
|
|
2640
2692
|
// ======================================================
|
|
2641
2693
|
// 🌐 LOCALIZATION CHECK (FULLY DYNAMIC)
|
|
2642
2694
|
// ======================================================
|
|
2643
2695
|
|
|
2644
2696
|
|
|
2645
|
-
const jsRootDir = path.join(
|
|
2697
|
+
const jsRootDir = path.join(process.cwd(), "src", "js");
|
|
2646
2698
|
|
|
2647
2699
|
// 🔍 Detect OLD localization files in root js/
|
|
2648
2700
|
const oldLocalizationFiles = fs.readdirSync(jsRootDir)
|
|
@@ -2870,53 +2922,8 @@ const checkAndupdateDropInViteConfig = () => {
|
|
|
2870
2922
|
};
|
|
2871
2923
|
|
|
2872
2924
|
const syncAdmobAliasInViteConfig = () => {
|
|
2873
|
-
const
|
|
2874
|
-
|
|
2875
|
-
"vite.config.js"
|
|
2876
|
-
];
|
|
2877
|
-
|
|
2878
|
-
const viteConfigPath = possibleFiles
|
|
2879
|
-
.map(file => path.join(process.cwd(), file))
|
|
2880
|
-
.find(filePath => fs.existsSync(filePath));
|
|
2881
|
-
|
|
2882
|
-
if (!viteConfigPath) {
|
|
2883
|
-
console.warn("⚠️ No vite config found. Skipping AdMob alias sync.");
|
|
2884
|
-
return;
|
|
2885
|
-
}
|
|
2886
|
-
|
|
2887
|
-
const adsDir = path.join(process.cwd(), "src", "js", "Ads");
|
|
2888
|
-
|
|
2889
|
-
if (!fs.existsSync(adsDir)) {
|
|
2890
|
-
console.log("ℹ️ Ads folder not found. Keeping existing @admob alias.");
|
|
2891
|
-
return;
|
|
2892
|
-
}
|
|
2893
|
-
|
|
2894
|
-
const nextGenFile = getLatestAdmobNextgenFileName(adsDir);
|
|
2895
|
-
|
|
2896
|
-
if (!nextGenFile) {
|
|
2897
|
-
console.log("ℹ️ No admob-emi-nextgen-x.x.js file found. Keeping existing @admob alias.");
|
|
2898
|
-
return;
|
|
2899
|
-
}
|
|
2900
|
-
|
|
2901
|
-
const nextGenRelativePath = `./src/js/Ads/${nextGenFile}`;
|
|
2902
|
-
|
|
2903
|
-
let viteContent = fs.readFileSync(viteConfigPath, "utf8");
|
|
2904
|
-
const nextGenAliasLine = ` '@admob': path.resolve(__dirname, '${nextGenRelativePath}'),`;
|
|
2905
|
-
const aliasLineRegex = /[ \t]*['"]@admob['"]:\s*path\.resolve\(__dirname,\s*['"][^'"]+['"]\),/;
|
|
2906
|
-
|
|
2907
|
-
if (aliasLineRegex.test(viteContent) && viteContent.includes(nextGenAliasLine)) {
|
|
2908
|
-
console.log(`ℹ️ @admob already points to ${nextGenRelativePath}.`);
|
|
2909
|
-
return;
|
|
2910
|
-
}
|
|
2911
|
-
|
|
2912
|
-
if (!aliasLineRegex.test(viteContent)) {
|
|
2913
|
-
console.warn("⚠️ @admob alias line not found in vite config. Skipping alias sync.");
|
|
2914
|
-
return;
|
|
2915
|
-
}
|
|
2916
|
-
|
|
2917
|
-
viteContent = viteContent.replace(aliasLineRegex, nextGenAliasLine);
|
|
2918
|
-
fs.writeFileSync(viteConfigPath, viteContent, "utf8");
|
|
2919
|
-
console.log(`✅ @admob alias updated to ${nextGenRelativePath}`);
|
|
2925
|
+
const latest = findAdmobPackage(path.join(process.cwd(), 'src', 'js', 'Ads'));
|
|
2926
|
+
if (latest) syncAdmobImports(process.cwd(), latest);
|
|
2920
2927
|
};
|
|
2921
2928
|
|
|
2922
2929
|
|
|
@@ -3271,34 +3278,13 @@ const ensureAdmobNextgenFiles = async () => {
|
|
|
3271
3278
|
return;
|
|
3272
3279
|
}
|
|
3273
3280
|
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
const nextgenFile = (() => {
|
|
3277
|
-
if (!localNextgenFile) return remoteNextgenFile;
|
|
3278
|
-
if (!remoteNextgenFile) return localNextgenFile;
|
|
3279
|
-
|
|
3280
|
-
const localVersion = extractVersionFromFileName(localNextgenFile);
|
|
3281
|
-
const remoteVersion = extractVersionFromFileName(remoteNextgenFile);
|
|
3282
|
-
return compareVersionStrings(remoteVersion, localVersion) > 0 ? remoteNextgenFile : localNextgenFile;
|
|
3283
|
-
})();
|
|
3284
|
-
|
|
3285
|
-
if (!nextgenFile) {
|
|
3286
|
-
console.error("❌ No local or remote admob-emi-nextgen file found for sync.");
|
|
3287
|
-
process.exit(1);
|
|
3288
|
-
}
|
|
3289
|
-
|
|
3290
|
-
const nextgenPath = path.join(adsDir, nextgenFile);
|
|
3281
|
+
await syncAdmobNextgen({ projectRoot: process.cwd(), versions: await fetchVersions() });
|
|
3282
|
+
sourceFileInventory = null;
|
|
3291
3283
|
const nextgenConfigPath = path.join(adsDir, ADMOB_NEXTGEN_CONFIG);
|
|
3292
3284
|
const oldConfigPath = path.join(adsDir, ADMOB_OLD_CONFIG);
|
|
3293
|
-
const
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
const downloaded = await downloadOptionalCodeplayFile(nextgenFile, nextgenPath);
|
|
3297
|
-
if (!downloaded) {
|
|
3298
|
-
console.error(`❌ ${nextgenFile} missing and live download failed.`);
|
|
3299
|
-
process.exit(1);
|
|
3300
|
-
}
|
|
3301
|
-
}
|
|
3285
|
+
const templateDir = path.join(process.cwd(), 'agent-temp', 'admob-config-sync');
|
|
3286
|
+
fs.mkdirSync(templateDir, { recursive: true });
|
|
3287
|
+
const tempTemplatePath = path.join(templateDir, ADMOB_NEXTGEN_CONFIG);
|
|
3302
3288
|
|
|
3303
3289
|
let templateConfig = ADMOB_NEXTGEN_DEFAULTS;
|
|
3304
3290
|
|
|
@@ -3789,6 +3775,7 @@ const ensureIapDesignInCapacitorConfig = (iapConfig) => {
|
|
|
3789
3775
|
};
|
|
3790
3776
|
|
|
3791
3777
|
const getCurrentStoreId = () => {
|
|
3778
|
+
if (buildPlatform === 'ios') return 6;
|
|
3792
3779
|
const envStoreId = Number(process.env.VITE_STORE_ID);
|
|
3793
3780
|
if (Number.isInteger(envStoreId) && envStoreId > 0) return envStoreId;
|
|
3794
3781
|
|
|
@@ -3976,6 +3963,17 @@ const syncRevenueCatIapSetup = () => {
|
|
|
3976
3963
|
console.log(`ℹ️ RevenueCat package is not required for store id ${storeId}.`);
|
|
3977
3964
|
}
|
|
3978
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);
|
|
3979
3977
|
ensureAndroidPermission("com.android.vending.BILLING", store?.usesGoogleBilling === true && revenueCatEnabledForCurrentStore);
|
|
3980
3978
|
|
|
3981
3979
|
if (iapConfig.samsung === true && revenueCatEnabled) {
|
|
@@ -4245,8 +4243,8 @@ const validateAndRestoreSignDetails=()=>{
|
|
|
4245
4243
|
|
|
4246
4244
|
|
|
4247
4245
|
const filePath = path.join(
|
|
4248
|
-
|
|
4249
|
-
"
|
|
4246
|
+
process.cwd(),
|
|
4247
|
+
"node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java"
|
|
4250
4248
|
);
|
|
4251
4249
|
|
|
4252
4250
|
const SYSTEM_BARS_PATCH_MARKER = "CODEPLAY_KEYBOARD_INSET_FIX";
|
|
@@ -4464,17 +4462,23 @@ function syncAndroidCordovaResourceKeep() {
|
|
|
4464
4462
|
}
|
|
4465
4463
|
|
|
4466
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
|
+
}
|
|
4467
4471
|
validateThemeFolderLocation();
|
|
4468
4472
|
validateAndRestoreSignDetails();
|
|
4469
4473
|
ensureMandatoryCapacitorPlugins();
|
|
4470
4474
|
|
|
4471
4475
|
await loadPluginVersions(); // 🔥 NEW
|
|
4472
4476
|
await syncAgentInstructions();
|
|
4477
|
+
await checkPlugins();
|
|
4473
4478
|
|
|
4474
4479
|
await syncAdmobNextgenMigration();
|
|
4475
4480
|
syncCodeplaySystemBarsPackage();
|
|
4476
4481
|
syncSystemBarsSafeAreaMigration();
|
|
4477
|
-
await checkPlugins();
|
|
4478
4482
|
ensureIapStartupOnHomePage();
|
|
4479
4483
|
syncRevenueCatIapSetup();
|
|
4480
4484
|
syncFirebaseAnalyticsSetup();
|