codeplay-common 4.0.5 → 4.0.8
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/.gitattributes +2 -2
- package/LICENSE +21 -21
- package/README.md +56 -35
- package/files/buildCodeplay/codeplayBeforeBuild-6.2.js +731 -43
- package/files/buildCodeplay/versions.json +2 -2
- package/files/finalrelease +937 -937
- package/files/iap-install-2.js +145 -145
- package/files/ionic.config.json +6 -6
- package/files/scripts/setup-baseline-profile.js +241 -241
- package/package.json +16 -16
- package/scripts/sync-files.js +105 -105
- package/scripts/uninstall.js +104 -104
|
@@ -272,9 +272,61 @@ function compareWithBeta(installedVersion, minVersion, isBeta) {
|
|
|
272
272
|
|
|
273
273
|
|
|
274
274
|
|
|
275
|
+
const ensureAnalyticsFlagsInConfig = (config) => {
|
|
276
|
+
const analyticsFlagKey = 'ANALYTICS_ENABLED';
|
|
277
|
+
const legacyAnalyticsFlagKey = ['ANALY', 'STICS_ENABLED'].join('');
|
|
278
|
+
let updated = false;
|
|
279
|
+
|
|
280
|
+
if (!config.android) {
|
|
281
|
+
config.android = {};
|
|
282
|
+
updated = true;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (!config.ios) {
|
|
286
|
+
config.ios = {};
|
|
287
|
+
updated = true;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const syncPlatformFlag = (platformName, platformConfig) => {
|
|
291
|
+
const existingValue = platformConfig[analyticsFlagKey];
|
|
292
|
+
const legacyValue = platformConfig[legacyAnalyticsFlagKey];
|
|
293
|
+
let nextValue = false;
|
|
294
|
+
|
|
295
|
+
if (typeof existingValue === 'boolean') {
|
|
296
|
+
nextValue = existingValue;
|
|
297
|
+
} else if (typeof legacyValue === 'boolean') {
|
|
298
|
+
nextValue = legacyValue;
|
|
299
|
+
} else if (existingValue !== undefined) {
|
|
300
|
+
console.warn(`⚠️ ${platformName}.ANALYTICS_ENABLED should be true or false. Automatically setting it to false.`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (platformConfig[analyticsFlagKey] !== nextValue) {
|
|
304
|
+
platformConfig[analyticsFlagKey] = nextValue;
|
|
305
|
+
updated = true;
|
|
306
|
+
console.warn(`⚠️ ${platformName}.ANALYTICS_ENABLED added/updated as ${nextValue}.`);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (legacyAnalyticsFlagKey in platformConfig) {
|
|
310
|
+
delete platformConfig[legacyAnalyticsFlagKey];
|
|
311
|
+
updated = true;
|
|
312
|
+
console.warn(`⚠️ ${platformName}.ANALYTICS_ENABLED spelling corrected.`);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (nextValue === false) {
|
|
316
|
+
console.warn(`⚠️ Google Analytics is disabled for ${platformName}. Mostly recommended to enable it when IAP is available.`);
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
syncPlatformFlag('android', config.android);
|
|
321
|
+
syncPlatformFlag('ios', config.ios);
|
|
322
|
+
|
|
323
|
+
return updated;
|
|
324
|
+
};
|
|
325
|
+
|
|
275
326
|
const checkAppUniqueId=()=>{
|
|
276
327
|
|
|
277
328
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
329
|
+
const analyticsFlagsUpdated = ensureAnalyticsFlagsInConfig(config);
|
|
278
330
|
|
|
279
331
|
const appUniqueId = config.android?.APP_UNIQUE_ID;
|
|
280
332
|
const RESIZEABLE_ACTIVITY = config.android?.RESIZEABLE_ACTIVITY;
|
|
@@ -313,14 +365,22 @@ const checkAppUniqueId=()=>{
|
|
|
313
365
|
logErrorMessage+='❌ APP_UNIQUE_ID must be an integer. Example: 1, 2, 3, etc.';
|
|
314
366
|
}
|
|
315
367
|
|
|
316
|
-
|
|
317
|
-
|
|
318
368
|
if(logErrorMessage!="")
|
|
319
369
|
{
|
|
370
|
+
if (analyticsFlagsUpdated) {
|
|
371
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
372
|
+
console.log('✅ capacitor.config.json analytics flags synced.');
|
|
373
|
+
}
|
|
374
|
+
|
|
320
375
|
console.error(logErrorMessage);
|
|
321
376
|
process.exit(1)
|
|
322
377
|
}
|
|
323
378
|
|
|
379
|
+
if (analyticsFlagsUpdated) {
|
|
380
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
381
|
+
console.log('✅ capacitor.config.json analytics flags synced.');
|
|
382
|
+
}
|
|
383
|
+
|
|
324
384
|
|
|
325
385
|
console.log(`✅ APP_UNIQUE_ID is valid: ${appUniqueId}`);
|
|
326
386
|
|
|
@@ -2520,6 +2580,623 @@ const syncAdmobAliasInViteConfig = () => {
|
|
|
2520
2580
|
};
|
|
2521
2581
|
|
|
2522
2582
|
|
|
2583
|
+
const getViteConfigPath = () => {
|
|
2584
|
+
const possibleFiles = [
|
|
2585
|
+
"vite.config.mjs",
|
|
2586
|
+
"vite.config.js"
|
|
2587
|
+
];
|
|
2588
|
+
|
|
2589
|
+
return possibleFiles
|
|
2590
|
+
.map(file => path.join(process.cwd(), file))
|
|
2591
|
+
.find(filePath => fs.existsSync(filePath));
|
|
2592
|
+
};
|
|
2593
|
+
|
|
2594
|
+
const getLatestIapDir = () => {
|
|
2595
|
+
const adsDir = path.join(process.cwd(), "src", "js", "Ads");
|
|
2596
|
+
|
|
2597
|
+
if (!fs.existsSync(adsDir)) return null;
|
|
2598
|
+
|
|
2599
|
+
const iapDirs = fs.readdirSync(adsDir, { withFileTypes: true })
|
|
2600
|
+
.filter(entry => entry.isDirectory() && /^IAP-\d+(\.\d+)*$/.test(entry.name))
|
|
2601
|
+
.map(entry => entry.name)
|
|
2602
|
+
.sort((a, b) => {
|
|
2603
|
+
const versionA = a.match(/(\d+(?:\.\d+)*)/)[1].split(".").map(Number);
|
|
2604
|
+
const versionB = b.match(/(\d+(?:\.\d+)*)/)[1].split(".").map(Number);
|
|
2605
|
+
|
|
2606
|
+
for (let i = 0; i < Math.max(versionA.length, versionB.length); i++) {
|
|
2607
|
+
const diff = (versionB[i] || 0) - (versionA[i] || 0);
|
|
2608
|
+
if (diff !== 0) return diff;
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
return 0;
|
|
2612
|
+
});
|
|
2613
|
+
|
|
2614
|
+
return iapDirs.length > 0 ? path.join(adsDir, iapDirs[0]) : null;
|
|
2615
|
+
};
|
|
2616
|
+
|
|
2617
|
+
const getAnalyticsConfig = () => {
|
|
2618
|
+
const config = fs.existsSync(configPath)
|
|
2619
|
+
? JSON.parse(fs.readFileSync(configPath, "utf8"))
|
|
2620
|
+
: {};
|
|
2621
|
+
|
|
2622
|
+
const analyticsFlagKey = "ANALYTICS_ENABLED";
|
|
2623
|
+
const androidEnabled = config.android?.[analyticsFlagKey] ?? false;
|
|
2624
|
+
const iosEnabled = config.ios?.[analyticsFlagKey] ?? false;
|
|
2625
|
+
|
|
2626
|
+
return {
|
|
2627
|
+
androidEnabled: androidEnabled === true,
|
|
2628
|
+
iosEnabled: iosEnabled === true,
|
|
2629
|
+
enabled: androidEnabled === true || iosEnabled === true
|
|
2630
|
+
};
|
|
2631
|
+
};
|
|
2632
|
+
|
|
2633
|
+
const isPackageAvailable = (packageName) => {
|
|
2634
|
+
if (!fs.existsSync(packageJsonPath)) return false;
|
|
2635
|
+
|
|
2636
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
2637
|
+
|
|
2638
|
+
return Boolean(
|
|
2639
|
+
packageJson.dependencies?.[packageName] ||
|
|
2640
|
+
packageJson.devDependencies?.[packageName] ||
|
|
2641
|
+
fs.existsSync(path.join(process.cwd(), "node_modules", packageName, "package.json"))
|
|
2642
|
+
);
|
|
2643
|
+
};
|
|
2644
|
+
|
|
2645
|
+
const sourceImportsPackage = (packageName, ignoredFilePath) => {
|
|
2646
|
+
const sourceDir = path.join(process.cwd(), "src");
|
|
2647
|
+
if (!fs.existsSync(sourceDir)) return false;
|
|
2648
|
+
|
|
2649
|
+
const escapedPackage = packageName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2650
|
+
const importRegex = new RegExp(`(?:from\\s*['"]${escapedPackage}(?:/[^'"]*)?['"]|import\\s*['"]${escapedPackage}(?:/[^'"]*)?['"]|import\\s*\\(\\s*['"]${escapedPackage}(?:/[^'"]*)?['"]\\s*\\)|require\\s*\\(\\s*['"]${escapedPackage}(?:/[^'"]*)?['"]\\s*\\))`);
|
|
2651
|
+
|
|
2652
|
+
const scan = (dir) => {
|
|
2653
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
2654
|
+
const fullPath = path.join(dir, entry.name);
|
|
2655
|
+
|
|
2656
|
+
if (ignoredFilePath && path.resolve(fullPath) === path.resolve(ignoredFilePath)) {
|
|
2657
|
+
continue;
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
if (entry.isDirectory()) {
|
|
2661
|
+
if (scan(fullPath)) return true;
|
|
2662
|
+
continue;
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
if (!/\.(js|mjs|cjs|ts|tsx|jsx|f7)$/.test(entry.name)) continue;
|
|
2666
|
+
|
|
2667
|
+
const content = fs.readFileSync(fullPath, "utf8");
|
|
2668
|
+
if (importRegex.test(content)) return true;
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
return false;
|
|
2672
|
+
};
|
|
2673
|
+
|
|
2674
|
+
return scan(sourceDir);
|
|
2675
|
+
};
|
|
2676
|
+
|
|
2677
|
+
const runNpmCommand = (command) => {
|
|
2678
|
+
console.log(`🚀 ${command}`);
|
|
2679
|
+
execSync(command, { stdio: "inherit" });
|
|
2680
|
+
};
|
|
2681
|
+
|
|
2682
|
+
const syncSystemBarsSafeAreaMigration = () => {
|
|
2683
|
+
if (isPackageAvailable("@capacitor-community/safe-area")) {
|
|
2684
|
+
runNpmCommand("npm uninstall @capacitor-community/safe-area");
|
|
2685
|
+
} else {
|
|
2686
|
+
console.log("ℹ️ @capacitor-community/safe-area is not installed.");
|
|
2687
|
+
}
|
|
2688
|
+
|
|
2689
|
+
if (!fs.existsSync(configPath)) {
|
|
2690
|
+
console.warn("⚠️ capacitor.config.json not found. Skipping SystemBars config sync.");
|
|
2691
|
+
return;
|
|
2692
|
+
}
|
|
2693
|
+
|
|
2694
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
2695
|
+
if (!config.plugins) config.plugins = {};
|
|
2696
|
+
if (!config.plugins.SystemBars) config.plugins.SystemBars = {};
|
|
2697
|
+
|
|
2698
|
+
if (config.plugins.SystemBars.insetsHandling !== "css") {
|
|
2699
|
+
config.plugins.SystemBars.insetsHandling = "css";
|
|
2700
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
2701
|
+
console.log('✅ capacitor.config.json SystemBars.insetsHandling set to "css".');
|
|
2702
|
+
} else {
|
|
2703
|
+
console.log('ℹ️ capacitor.config.json SystemBars.insetsHandling already "css".');
|
|
2704
|
+
}
|
|
2705
|
+
};
|
|
2706
|
+
|
|
2707
|
+
const ensureFirebaseAnalyticsWrapper = (analyticsEnabled) => {
|
|
2708
|
+
const analyticsDir = getLatestIapDir();
|
|
2709
|
+
const legacyAnalyticsDir = path.join(process.cwd(), "src", "js", "analytics");
|
|
2710
|
+
const legacyAnalyticsFile = path.join(legacyAnalyticsDir, "firebase-analytics.js");
|
|
2711
|
+
|
|
2712
|
+
if (!analyticsDir) {
|
|
2713
|
+
console.warn("⚠️ No IAP-x.x folder found. Skipping Firebase analytics wrapper sync.");
|
|
2714
|
+
return null;
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
const analyticsFile = path.join(analyticsDir, "firebase-analytics.js");
|
|
2718
|
+
|
|
2719
|
+
if (!fs.existsSync(analyticsDir)) {
|
|
2720
|
+
fs.mkdirSync(analyticsDir, { recursive: true });
|
|
2721
|
+
}
|
|
2722
|
+
|
|
2723
|
+
const activeWrapper = `import { Capacitor, registerPlugin } from '@capacitor/core';
|
|
2724
|
+
|
|
2725
|
+
const FirebaseAnalytics = registerPlugin('FirebaseAnalytics');
|
|
2726
|
+
|
|
2727
|
+
const isEnabledValue = (value) => value === true || value === 'true';
|
|
2728
|
+
|
|
2729
|
+
const canUseNativeAnalytics = () => {
|
|
2730
|
+
if (!Capacitor.isNativePlatform()) return false;
|
|
2731
|
+
|
|
2732
|
+
const platform = Capacitor.getPlatform();
|
|
2733
|
+
|
|
2734
|
+
if (platform === 'android') {
|
|
2735
|
+
return isEnabledValue(import.meta.env.VITE_ANDROID_ANALYTICS_ENABLED);
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
if (platform === 'ios') {
|
|
2739
|
+
return isEnabledValue(import.meta.env.VITE_IOS_ANALYTICS_ENABLED);
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2742
|
+
return false;
|
|
2743
|
+
};
|
|
2744
|
+
|
|
2745
|
+
const cleanParams = (params = {}) => {
|
|
2746
|
+
return Object.entries(params).reduce((result, [key, value]) => {
|
|
2747
|
+
if (value === undefined || value === null || value === '') return result;
|
|
2748
|
+
if (typeof value === 'number' && Number.isNaN(value)) return result;
|
|
2749
|
+
|
|
2750
|
+
result[key] = value;
|
|
2751
|
+
return result;
|
|
2752
|
+
}, {});
|
|
2753
|
+
};
|
|
2754
|
+
|
|
2755
|
+
const trackEvent = async (name, params = {}) => {
|
|
2756
|
+
if (!canUseNativeAnalytics()) return;
|
|
2757
|
+
|
|
2758
|
+
try {
|
|
2759
|
+
await FirebaseAnalytics.logEvent({
|
|
2760
|
+
name,
|
|
2761
|
+
params: cleanParams(params),
|
|
2762
|
+
});
|
|
2763
|
+
} catch (err) {
|
|
2764
|
+
console.warn(\`Firebase analytics event failed: \${name}\`, err);
|
|
2765
|
+
}
|
|
2766
|
+
};
|
|
2767
|
+
|
|
2768
|
+
export const trackSubscriptionScreenViewed = (params) => {
|
|
2769
|
+
trackEvent('subscription_screen_view', params);
|
|
2770
|
+
};
|
|
2771
|
+
|
|
2772
|
+
export const trackSubscriptionCheckoutStarted = (params) => {
|
|
2773
|
+
trackEvent('subscription_checkout_start', params);
|
|
2774
|
+
};
|
|
2775
|
+
|
|
2776
|
+
export const trackSubscriptionPurchased = (params) => {
|
|
2777
|
+
trackEvent('subscription_purchase', params);
|
|
2778
|
+
};
|
|
2779
|
+
|
|
2780
|
+
export const trackConsumablePurchased = (params) => {
|
|
2781
|
+
trackEvent('consumable_purchase', params);
|
|
2782
|
+
};
|
|
2783
|
+
`;
|
|
2784
|
+
|
|
2785
|
+
const noopWrapper = `const trackEvent = () => {};
|
|
2786
|
+
|
|
2787
|
+
export const trackSubscriptionScreenViewed = trackEvent;
|
|
2788
|
+
export const trackSubscriptionCheckoutStarted = trackEvent;
|
|
2789
|
+
export const trackSubscriptionPurchased = trackEvent;
|
|
2790
|
+
export const trackConsumablePurchased = trackEvent;
|
|
2791
|
+
`;
|
|
2792
|
+
|
|
2793
|
+
const nextContent = analyticsEnabled ? activeWrapper : noopWrapper;
|
|
2794
|
+
const currentContent = fs.existsSync(analyticsFile) ? fs.readFileSync(analyticsFile, "utf8") : "";
|
|
2795
|
+
|
|
2796
|
+
if (currentContent !== nextContent) {
|
|
2797
|
+
fs.writeFileSync(analyticsFile, nextContent, "utf8");
|
|
2798
|
+
console.log(`✅ Firebase analytics wrapper ${analyticsEnabled ? "enabled" : "disabled"}: ${path.relative(process.cwd(), analyticsFile)}`);
|
|
2799
|
+
} else {
|
|
2800
|
+
console.log(`ℹ️ Firebase analytics wrapper already ${analyticsEnabled ? "enabled" : "disabled"}.`);
|
|
2801
|
+
}
|
|
2802
|
+
|
|
2803
|
+
if (fs.existsSync(legacyAnalyticsFile)) {
|
|
2804
|
+
fs.unlinkSync(legacyAnalyticsFile);
|
|
2805
|
+
console.log("✅ Removed old Firebase analytics wrapper: src/js/analytics/firebase-analytics.js");
|
|
2806
|
+
}
|
|
2807
|
+
|
|
2808
|
+
if (fs.existsSync(legacyAnalyticsDir) && fs.readdirSync(legacyAnalyticsDir).length === 0) {
|
|
2809
|
+
fs.rmdirSync(legacyAnalyticsDir);
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
return analyticsFile;
|
|
2813
|
+
};
|
|
2814
|
+
|
|
2815
|
+
const syncFirebaseAnalyticsPackages = () => {
|
|
2816
|
+
const analyticsConfig = getAnalyticsConfig();
|
|
2817
|
+
|
|
2818
|
+
if (analyticsConfig.enabled) {
|
|
2819
|
+
if (!isPackageAvailable("@capacitor-firebase/analytics") || !isPackageAvailable("firebase")) {
|
|
2820
|
+
runNpmCommand("npm install @capacitor-firebase/analytics firebase");
|
|
2821
|
+
} else {
|
|
2822
|
+
console.log("ℹ️ Firebase Analytics packages already installed.");
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
ensureFirebaseAnalyticsWrapper(true);
|
|
2826
|
+
return;
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2829
|
+
const analyticsFile = ensureFirebaseAnalyticsWrapper(false);
|
|
2830
|
+
|
|
2831
|
+
if (isPackageAvailable("@capacitor-firebase/analytics")) {
|
|
2832
|
+
runNpmCommand("npm uninstall @capacitor-firebase/analytics");
|
|
2833
|
+
} else {
|
|
2834
|
+
console.log("ℹ️ @capacitor-firebase/analytics is not installed.");
|
|
2835
|
+
}
|
|
2836
|
+
|
|
2837
|
+
if (isPackageAvailable("firebase")) {
|
|
2838
|
+
if (sourceImportsPackage("firebase", analyticsFile)) {
|
|
2839
|
+
console.log("ℹ️ Keeping firebase package because other source files import it.");
|
|
2840
|
+
} else {
|
|
2841
|
+
runNpmCommand("npm uninstall firebase");
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
};
|
|
2845
|
+
|
|
2846
|
+
const syncFirebaseAnalyticsPodfile = () => {
|
|
2847
|
+
const podfilePath = path.join(process.cwd(), "ios", "App", "Podfile");
|
|
2848
|
+
if (!fs.existsSync(podfilePath)) return;
|
|
2849
|
+
|
|
2850
|
+
const { iosEnabled } = getAnalyticsConfig();
|
|
2851
|
+
const basePodLine = " pod 'CapacitorFirebaseAnalytics', :path => '../../node_modules/@capacitor-firebase/analytics'";
|
|
2852
|
+
const analyticsPodLine = " pod 'CapacitorFirebaseAnalytics/Analytics', :path => '../../node_modules/@capacitor-firebase/analytics'";
|
|
2853
|
+
|
|
2854
|
+
let content = fs.readFileSync(podfilePath, "utf8");
|
|
2855
|
+
let nextContent = content;
|
|
2856
|
+
|
|
2857
|
+
if (iosEnabled) {
|
|
2858
|
+
if (!nextContent.includes(basePodLine)) {
|
|
2859
|
+
nextContent = nextContent.replace(
|
|
2860
|
+
/(pod 'CapacitorCommunitySafeArea'[^\n]*\r?\n)/,
|
|
2861
|
+
`$1${basePodLine}\n`
|
|
2862
|
+
);
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2865
|
+
if (!nextContent.includes(analyticsPodLine)) {
|
|
2866
|
+
nextContent = nextContent.replace(
|
|
2867
|
+
/(# Add your Pods here\r?\n)/,
|
|
2868
|
+
`$1${analyticsPodLine}\n`
|
|
2869
|
+
);
|
|
2870
|
+
}
|
|
2871
|
+
} else {
|
|
2872
|
+
nextContent = nextContent
|
|
2873
|
+
.split(/\r?\n/)
|
|
2874
|
+
.filter(line => !line.includes("CapacitorFirebaseAnalytics"))
|
|
2875
|
+
.join("\n");
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
if (nextContent !== content) {
|
|
2879
|
+
fs.writeFileSync(podfilePath, nextContent, "utf8");
|
|
2880
|
+
console.log(`✅ iOS Firebase Analytics Podfile entries ${iosEnabled ? "enabled" : "removed"}.`);
|
|
2881
|
+
} else {
|
|
2882
|
+
console.log(`ℹ️ iOS Firebase Analytics Podfile entries already ${iosEnabled ? "enabled" : "disabled"}.`);
|
|
2883
|
+
}
|
|
2884
|
+
};
|
|
2885
|
+
|
|
2886
|
+
const ensureImportOrRequire = (content, moduleName, esmLine, cjsLine) => {
|
|
2887
|
+
const escaped = moduleName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2888
|
+
if (new RegExp(`from\\s*['"]${escaped}['"]|require\\s*\\(\\s*['"]${escaped}['"]\\s*\\)`).test(content)) {
|
|
2889
|
+
return content;
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2892
|
+
const isCommonJs = /module\.exports|require\s*\(/.test(content);
|
|
2893
|
+
const line = isCommonJs ? cjsLine : esmLine;
|
|
2894
|
+
|
|
2895
|
+
return `${line}\n${content}`;
|
|
2896
|
+
};
|
|
2897
|
+
|
|
2898
|
+
const ensureViteDefineEntry = (viteContent, key, valueExpression) => {
|
|
2899
|
+
const entry = ` '${key}': JSON.stringify(${valueExpression}),`;
|
|
2900
|
+
|
|
2901
|
+
if (viteContent.includes(`'${key}'`) || viteContent.includes(`"${key}"`)) {
|
|
2902
|
+
return viteContent;
|
|
2903
|
+
}
|
|
2904
|
+
|
|
2905
|
+
if (/define\s*:\s*{/.test(viteContent)) {
|
|
2906
|
+
return viteContent.replace(/define\s*:\s*{\s*/, match => `${match}\n${entry}\n`);
|
|
2907
|
+
}
|
|
2908
|
+
|
|
2909
|
+
const defineBlock = ` define: {
|
|
2910
|
+
'${key}': JSON.stringify(${valueExpression}),
|
|
2911
|
+
},`;
|
|
2912
|
+
|
|
2913
|
+
if (/\n\s*publicDir\s*:\s*[^,\n]+,?/.test(viteContent)) {
|
|
2914
|
+
return viteContent.replace(
|
|
2915
|
+
/(\n\s*publicDir\s*:\s*[^,\n]+,?)/,
|
|
2916
|
+
`$1\n${defineBlock}`
|
|
2917
|
+
);
|
|
2918
|
+
}
|
|
2919
|
+
|
|
2920
|
+
return viteContent.replace(
|
|
2921
|
+
/(return\s+{)/,
|
|
2922
|
+
`$1\n${defineBlock}`
|
|
2923
|
+
);
|
|
2924
|
+
};
|
|
2925
|
+
|
|
2926
|
+
const ensurePrivacyAndAnalyticsViteConfig = () => {
|
|
2927
|
+
const viteConfigPath = getViteConfigPath();
|
|
2928
|
+
|
|
2929
|
+
if (!viteConfigPath) {
|
|
2930
|
+
console.warn("⚠️ No vite config found. Skipping privacy/analytics Vite sync.");
|
|
2931
|
+
return;
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
let viteContent = fs.readFileSync(viteConfigPath, "utf8");
|
|
2935
|
+
const originalContent = viteContent;
|
|
2936
|
+
|
|
2937
|
+
viteContent = ensureImportOrRequire(
|
|
2938
|
+
viteContent,
|
|
2939
|
+
"fs",
|
|
2940
|
+
"import fs from 'fs';",
|
|
2941
|
+
"const fs = require('fs');"
|
|
2942
|
+
);
|
|
2943
|
+
|
|
2944
|
+
viteContent = ensureImportOrRequire(
|
|
2945
|
+
viteContent,
|
|
2946
|
+
"path",
|
|
2947
|
+
"import path from 'path';",
|
|
2948
|
+
"const path = require('path');"
|
|
2949
|
+
);
|
|
2950
|
+
|
|
2951
|
+
if (!/\bcapacitorConfig\b/.test(viteContent)) {
|
|
2952
|
+
viteContent = viteContent.replace(
|
|
2953
|
+
/(\r?\nexport\s+default|\r?\nmodule\.exports)/,
|
|
2954
|
+
`\nconst capacitorConfig = JSON.parse(fs.readFileSync(path.resolve(__dirname, './capacitor.config.json'), 'utf8'));\n$1`
|
|
2955
|
+
);
|
|
2956
|
+
}
|
|
2957
|
+
|
|
2958
|
+
if (!/\bAPP_UNIQUE_ID\b/.test(viteContent)) {
|
|
2959
|
+
viteContent = viteContent.replace(
|
|
2960
|
+
/(const capacitorConfig = JSON\.parse\(fs\.readFileSync\(path\.resolve\(__dirname,\s*['"]\.\/capacitor\.config\.json['"]\),\s*['"]utf8['"]\)\);\r?\n)/,
|
|
2961
|
+
`$1const APP_UNIQUE_ID = capacitorConfig.android?.APP_UNIQUE_ID ?? '';\n`
|
|
2962
|
+
);
|
|
2963
|
+
}
|
|
2964
|
+
|
|
2965
|
+
if (!/\bANDROID_ANALYTICS_ENABLED\b/.test(viteContent)) {
|
|
2966
|
+
viteContent = viteContent.replace(
|
|
2967
|
+
/(const APP_UNIQUE_ID = capacitorConfig\.android\?\.APP_UNIQUE_ID \?\? ['"]['"];\r?\n)/,
|
|
2968
|
+
`$1const ANDROID_ANALYTICS_ENABLED = capacitorConfig.android?.ANALYTICS_ENABLED ?? false;\n`
|
|
2969
|
+
);
|
|
2970
|
+
}
|
|
2971
|
+
|
|
2972
|
+
if (!/\bIOS_ANALYTICS_ENABLED\b/.test(viteContent)) {
|
|
2973
|
+
viteContent = viteContent.replace(
|
|
2974
|
+
/(const ANDROID_ANALYTICS_ENABLED = capacitorConfig\.android\?\.ANALYTICS_ENABLED \?\? false;\r?\n)/,
|
|
2975
|
+
`$1const IOS_ANALYTICS_ENABLED = capacitorConfig.ios?.ANALYTICS_ENABLED ?? false;\n`
|
|
2976
|
+
);
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2979
|
+
if (!/\bIAP_DESIGN\b/.test(viteContent)) {
|
|
2980
|
+
viteContent = viteContent.replace(
|
|
2981
|
+
/(const IOS_ANALYTICS_ENABLED = capacitorConfig\.ios\?\.ANALYTICS_ENABLED \?\? false;\r?\n)/,
|
|
2982
|
+
`$1const IAP_DESIGN = capacitorConfig["IAP-Design"] ?? 'default';\n`
|
|
2983
|
+
);
|
|
2984
|
+
}
|
|
2985
|
+
|
|
2986
|
+
viteContent = viteContent
|
|
2987
|
+
.replace(
|
|
2988
|
+
/const ANDROID_ANALYTICS_ENABLED = capacitorConfig\.android\?\.ANALY[ST]ICS_ENABLED \?\? capacitorConfig\.android\?\.ANALYTICS_ENABLED \?\? false;/g,
|
|
2989
|
+
"const ANDROID_ANALYTICS_ENABLED = capacitorConfig.android?.ANALYTICS_ENABLED ?? false;"
|
|
2990
|
+
)
|
|
2991
|
+
.replace(
|
|
2992
|
+
/const IOS_ANALYTICS_ENABLED = capacitorConfig\.ios\?\.ANALY[ST]ICS_ENABLED \?\? capacitorConfig\.ios\?\.ANALYTICS_ENABLED \?\? false;/g,
|
|
2993
|
+
"const IOS_ANALYTICS_ENABLED = capacitorConfig.ios?.ANALYTICS_ENABLED ?? false;"
|
|
2994
|
+
);
|
|
2995
|
+
|
|
2996
|
+
viteContent = ensureViteDefineEntry(viteContent, "import.meta.env.VITE_APP_UNIQUE_ID", "APP_UNIQUE_ID");
|
|
2997
|
+
viteContent = ensureViteDefineEntry(viteContent, "import.meta.env.VITE_ANDROID_ANALYTICS_ENABLED", "ANDROID_ANALYTICS_ENABLED");
|
|
2998
|
+
viteContent = ensureViteDefineEntry(viteContent, "import.meta.env.VITE_IOS_ANALYTICS_ENABLED", "IOS_ANALYTICS_ENABLED");
|
|
2999
|
+
viteContent = ensureViteDefineEntry(viteContent, "import.meta.env.VITE_IAP_DESIGN", "IAP_DESIGN");
|
|
3000
|
+
|
|
3001
|
+
if (viteContent !== originalContent) {
|
|
3002
|
+
fs.writeFileSync(viteConfigPath, viteContent, "utf8");
|
|
3003
|
+
console.log("✅ vite.config.(m)js privacy/analytics settings synced.");
|
|
3004
|
+
} else {
|
|
3005
|
+
console.log("ℹ️ vite.config.(m)js privacy/analytics settings already synced.");
|
|
3006
|
+
}
|
|
3007
|
+
};
|
|
3008
|
+
|
|
3009
|
+
const syncFirebaseAnalyticsSetup = () => {
|
|
3010
|
+
syncFirebaseAnalyticsPackages();
|
|
3011
|
+
syncFirebaseAnalyticsPodfile();
|
|
3012
|
+
ensurePrivacyAndAnalyticsViteConfig();
|
|
3013
|
+
};
|
|
3014
|
+
|
|
3015
|
+
const getAdmobIapConfigPath = () => {
|
|
3016
|
+
const possiblePaths = [
|
|
3017
|
+
path.join(process.cwd(), 'src', 'js', 'Ads', 'admob-ad-configuration-nextgen.json'),
|
|
3018
|
+
path.join(process.cwd(), 'src', 'js', 'Ads', 'admob-ad-configuration.json')
|
|
3019
|
+
];
|
|
3020
|
+
|
|
3021
|
+
return possiblePaths.find(fileExists);
|
|
3022
|
+
};
|
|
3023
|
+
|
|
3024
|
+
const getAdmobIapConfig = () => {
|
|
3025
|
+
const admobIapConfigPath = getAdmobIapConfigPath();
|
|
3026
|
+
|
|
3027
|
+
if (!admobIapConfigPath) {
|
|
3028
|
+
console.warn("⚠️ No AdMob configuration JSON found. Skipping RevenueCat IAP package sync.");
|
|
3029
|
+
return null;
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
try {
|
|
3033
|
+
return JSON.parse(fs.readFileSync(admobIapConfigPath, "utf8"));
|
|
3034
|
+
} catch (err) {
|
|
3035
|
+
console.error(`❌ Failed to read ${path.relative(process.cwd(), admobIapConfigPath)}`, err);
|
|
3036
|
+
process.exit(1);
|
|
3037
|
+
}
|
|
3038
|
+
};
|
|
3039
|
+
|
|
3040
|
+
const isAnyIapStoreEnabled = (iapConfig) => {
|
|
3041
|
+
return Boolean(
|
|
3042
|
+
iapConfig?.playstore === true ||
|
|
3043
|
+
iapConfig?.samsung === true ||
|
|
3044
|
+
iapConfig?.amazon === true ||
|
|
3045
|
+
iapConfig?.ios === true
|
|
3046
|
+
);
|
|
3047
|
+
};
|
|
3048
|
+
|
|
3049
|
+
const ensureIapDesignInCapacitorConfig = (iapConfig) => {
|
|
3050
|
+
if (!isAnyIapStoreEnabled(iapConfig)) return;
|
|
3051
|
+
|
|
3052
|
+
if (!fs.existsSync(configPath)) {
|
|
3053
|
+
console.warn("⚠️ capacitor.config.json not found. Skipping IAP-Design sync.");
|
|
3054
|
+
return;
|
|
3055
|
+
}
|
|
3056
|
+
|
|
3057
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
3058
|
+
|
|
3059
|
+
if (Object.prototype.hasOwnProperty.call(config, "IAP-Design")) {
|
|
3060
|
+
console.log("ℹ️ capacitor.config.json IAP-Design already configured.");
|
|
3061
|
+
return;
|
|
3062
|
+
}
|
|
3063
|
+
|
|
3064
|
+
config["IAP-Design"] = "default";
|
|
3065
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
3066
|
+
console.log('✅ Added "IAP-Design": "default" to capacitor.config.json.');
|
|
3067
|
+
};
|
|
3068
|
+
|
|
3069
|
+
const getCurrentStoreId = () => {
|
|
3070
|
+
const envStoreId = Number(process.env.VITE_STORE_ID);
|
|
3071
|
+
if (Number.isInteger(envStoreId) && envStoreId > 0) return envStoreId;
|
|
3072
|
+
|
|
3073
|
+
const viteConfigPath = getViteConfigPath();
|
|
3074
|
+
if (!viteConfigPath) return 1;
|
|
3075
|
+
|
|
3076
|
+
const viteConfigContent = fs.readFileSync(viteConfigPath, "utf8");
|
|
3077
|
+
const commonAliasMatch = viteConfigContent.match(/['"]@common['"]:\s*path\.resolve\(__dirname,\s*['"]([^'"]+)['"]\)/);
|
|
3078
|
+
|
|
3079
|
+
if (!commonAliasMatch) return 1;
|
|
3080
|
+
|
|
3081
|
+
const commonFilePath = path.resolve(path.dirname(viteConfigPath), commonAliasMatch[1]);
|
|
3082
|
+
if (!fs.existsSync(commonFilePath)) return 1;
|
|
3083
|
+
|
|
3084
|
+
const commonFileContent = fs.readFileSync(commonFilePath, "utf8");
|
|
3085
|
+
const storeIdMatch = commonFileContent.match(/export\s+let\s+_storeid\s*=\s*import\.meta\.env\.VITE_STORE_ID\s*\|\|\s*(\d+)\s*;/);
|
|
3086
|
+
|
|
3087
|
+
return storeIdMatch ? Number(storeIdMatch[1]) : 1;
|
|
3088
|
+
};
|
|
3089
|
+
|
|
3090
|
+
const getRevenueCatStoreState = (iapConfig) => {
|
|
3091
|
+
const storeId = getCurrentStoreId();
|
|
3092
|
+
const configuration = iapConfig.configuration || {};
|
|
3093
|
+
const storeMap = {
|
|
3094
|
+
1: {
|
|
3095
|
+
name: "PlayStore",
|
|
3096
|
+
enabled: iapConfig.playstore === true,
|
|
3097
|
+
apiKeyName: "IAP.configuration.playstore",
|
|
3098
|
+
apiKey: configuration.playstore,
|
|
3099
|
+
usesGoogleBilling: true
|
|
3100
|
+
},
|
|
3101
|
+
6: {
|
|
3102
|
+
name: "iOSStore",
|
|
3103
|
+
enabled: iapConfig.ios === true,
|
|
3104
|
+
apiKeyName: "IAP.configuration.ios",
|
|
3105
|
+
apiKey: configuration.ios,
|
|
3106
|
+
usesGoogleBilling: false
|
|
3107
|
+
},
|
|
3108
|
+
7: {
|
|
3109
|
+
name: "AmazonStore",
|
|
3110
|
+
enabled: iapConfig.amazon === true,
|
|
3111
|
+
apiKeyName: "IAP.configuration.amazon",
|
|
3112
|
+
apiKey: configuration.amazon,
|
|
3113
|
+
usesGoogleBilling: false
|
|
3114
|
+
}
|
|
3115
|
+
};
|
|
3116
|
+
|
|
3117
|
+
return {
|
|
3118
|
+
storeId,
|
|
3119
|
+
store: storeMap[storeId] || null
|
|
3120
|
+
};
|
|
3121
|
+
};
|
|
3122
|
+
|
|
3123
|
+
const ensureAndroidPermission = (permission, enabled) => {
|
|
3124
|
+
if (!fs.existsSync(androidManifestPath)) return false;
|
|
3125
|
+
|
|
3126
|
+
let manifestContent = fs.readFileSync(androidManifestPath, "utf8");
|
|
3127
|
+
const permissionLine = ` <uses-permission android:name="${permission}" />`;
|
|
3128
|
+
const permissionRegex = new RegExp(`^\\s*<uses-permission\\s+android:name="${permission.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"\\s*/?>\\s*\\r?\\n?`, "m");
|
|
3129
|
+
|
|
3130
|
+
if (enabled) {
|
|
3131
|
+
if (permissionRegex.test(manifestContent)) return false;
|
|
3132
|
+
|
|
3133
|
+
manifestContent = manifestContent.replace(
|
|
3134
|
+
/<\/manifest>\s*$/,
|
|
3135
|
+
`${permissionLine}\n</manifest>`
|
|
3136
|
+
);
|
|
3137
|
+
fs.writeFileSync(androidManifestPath, manifestContent, "utf8");
|
|
3138
|
+
console.log(`✅ Added Android permission: ${permission}`);
|
|
3139
|
+
return true;
|
|
3140
|
+
}
|
|
3141
|
+
|
|
3142
|
+
if (!permissionRegex.test(manifestContent)) return false;
|
|
3143
|
+
|
|
3144
|
+
manifestContent = manifestContent.replace(permissionRegex, "");
|
|
3145
|
+
fs.writeFileSync(androidManifestPath, manifestContent, "utf8");
|
|
3146
|
+
console.log(`✅ Removed Android permission: ${permission}`);
|
|
3147
|
+
return true;
|
|
3148
|
+
};
|
|
3149
|
+
|
|
3150
|
+
const syncRevenueCatIapSetup = () => {
|
|
3151
|
+
const admobConfig = getAdmobIapConfig();
|
|
3152
|
+
const iapConfig = admobConfig?.IAP;
|
|
3153
|
+
|
|
3154
|
+
if (!iapConfig) {
|
|
3155
|
+
console.log("ℹ️ IAP configuration not found. Skipping RevenueCat package sync.");
|
|
3156
|
+
return;
|
|
3157
|
+
}
|
|
3158
|
+
|
|
3159
|
+
ensureIapDesignInCapacitorConfig(iapConfig);
|
|
3160
|
+
|
|
3161
|
+
const revenueCatEnabled =
|
|
3162
|
+
iapConfig.playstore === true ||
|
|
3163
|
+
iapConfig.ios === true ||
|
|
3164
|
+
iapConfig.amazon === true;
|
|
3165
|
+
const { storeId, store } = getRevenueCatStoreState(iapConfig);
|
|
3166
|
+
const revenueCatEnabledForCurrentStore = store?.enabled === true;
|
|
3167
|
+
|
|
3168
|
+
if (revenueCatEnabledForCurrentStore && !store.apiKey) {
|
|
3169
|
+
console.error(`❌ RevenueCat IAP is enabled for ${store.name} but ${store.apiKeyName} is missing.`);
|
|
3170
|
+
process.exit(1);
|
|
3171
|
+
}
|
|
3172
|
+
|
|
3173
|
+
let packageChanged = false;
|
|
3174
|
+
|
|
3175
|
+
if (revenueCatEnabledForCurrentStore) {
|
|
3176
|
+
if (!isPackageAvailable("@revenuecat/purchases-capacitor")) {
|
|
3177
|
+
runNpmCommand("npm install @revenuecat/purchases-capacitor");
|
|
3178
|
+
packageChanged = true;
|
|
3179
|
+
} else {
|
|
3180
|
+
console.log(`ℹ️ RevenueCat package already installed for ${store.name}.`);
|
|
3181
|
+
}
|
|
3182
|
+
} else if (isPackageAvailable("@revenuecat/purchases-capacitor")) {
|
|
3183
|
+
runNpmCommand("npm uninstall @revenuecat/purchases-capacitor");
|
|
3184
|
+
packageChanged = true;
|
|
3185
|
+
} else {
|
|
3186
|
+
console.log(`ℹ️ RevenueCat package is not required for store id ${storeId}.`);
|
|
3187
|
+
}
|
|
3188
|
+
|
|
3189
|
+
ensureAndroidPermission("com.android.vending.BILLING", store?.usesGoogleBilling === true && revenueCatEnabledForCurrentStore);
|
|
3190
|
+
|
|
3191
|
+
if (iapConfig.samsung === true && revenueCatEnabled) {
|
|
3192
|
+
console.warn("⚠️ Samsung IAP uses cordova-plugin-samsungiap; PlayStore/Amazon/iOS use RevenueCat.");
|
|
3193
|
+
}
|
|
3194
|
+
|
|
3195
|
+
if (packageChanged) {
|
|
3196
|
+
runNpmCommand("npx cap sync");
|
|
3197
|
+
}
|
|
3198
|
+
};
|
|
3199
|
+
|
|
2523
3200
|
|
|
2524
3201
|
|
|
2525
3202
|
|
|
@@ -2692,11 +3369,14 @@ ensureGitignoreEntry('buildCodeplay/');
|
|
|
2692
3369
|
|
|
2693
3370
|
|
|
2694
3371
|
// Run the validation
|
|
2695
|
-
(async () => {
|
|
2696
|
-
|
|
2697
|
-
await loadPluginVersions(); // 🔥 NEW
|
|
2698
|
-
|
|
2699
|
-
|
|
3372
|
+
(async () => {
|
|
3373
|
+
|
|
3374
|
+
await loadPluginVersions(); // 🔥 NEW
|
|
3375
|
+
|
|
3376
|
+
syncSystemBarsSafeAreaMigration();
|
|
3377
|
+
await checkPlugins();
|
|
3378
|
+
syncRevenueCatIapSetup();
|
|
3379
|
+
syncFirebaseAnalyticsSetup();
|
|
2700
3380
|
checkAndupdateDropInViteConfig();
|
|
2701
3381
|
syncAdmobAliasInViteConfig();
|
|
2702
3382
|
checkAdmobConfigurationProperty()
|
|
@@ -2790,45 +3470,45 @@ const filePath = path.join(
|
|
|
2790
3470
|
"../node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java"
|
|
2791
3471
|
);
|
|
2792
3472
|
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
3473
|
+
const SYSTEM_BARS_PATCH_MARKER = "CODEPLAY_KEYBOARD_INSET_FIX";
|
|
3474
|
+
|
|
3475
|
+
function getSystemBarsPatchedBlock(originalBlock, content) {
|
|
3476
|
+
const isCapacitor842OrNewer = content.includes("private String insetsHandling = INSETS_HANDLING_CSS;");
|
|
3477
|
+
const safeAreaCondition = isCapacitor842OrNewer
|
|
3478
|
+
? "INSETS_HANDLING_CSS.equals(insetsHandling)"
|
|
3479
|
+
: "Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && hasViewportCover && insetHandlingEnabled";
|
|
3480
|
+
|
|
3481
|
+
return `if (shouldPassthroughInsets) {
|
|
3482
|
+
/* ${SYSTEM_BARS_PATCH_MARKER}
|
|
3483
|
+
${originalBlock.split("\n").map(line => " " + line).join("\n")}
|
|
3484
|
+
*/
|
|
3485
|
+
|
|
3486
|
+
// Codeplay fix: avoid adding IME height as WebView parent padding.
|
|
3487
|
+
v.setPadding(0, 0, 0, 0);
|
|
2797
3488
|
|
|
2798
|
-
if (
|
|
3489
|
+
if (${safeAreaCondition}) {
|
|
2799
3490
|
Insets safeAreaInsets = calcSafeAreaInsets(insets);
|
|
2800
3491
|
injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left);
|
|
2801
3492
|
}
|
|
2802
3493
|
|
|
2803
|
-
return
|
|
2804
|
-
.setInsets(
|
|
2805
|
-
WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout(),
|
|
2806
|
-
Insets.of(
|
|
2807
|
-
systemBarsInsets.left,
|
|
2808
|
-
systemBarsInsets.top,
|
|
2809
|
-
systemBarsInsets.right,
|
|
2810
|
-
getBottomInset(systemBarsInsets, keyboardVisible)
|
|
2811
|
-
)
|
|
2812
|
-
)
|
|
2813
|
-
.build();
|
|
3494
|
+
return insets; // WebView handles keyboard and safe-area sizing.
|
|
2814
3495
|
}`;
|
|
3496
|
+
}
|
|
2815
3497
|
|
|
2816
|
-
|
|
2817
|
-
const
|
|
2818
|
-
|
|
2819
|
-
${OLD_BLOCK.split("\n").map(line => " " + line).join("\n")}
|
|
2820
|
-
*/
|
|
2821
|
-
|
|
2822
|
-
// ✅ NEW LOGIC (CUSTOM FIX)
|
|
2823
|
-
v.setPadding(0, 0, 0, 0);
|
|
3498
|
+
function findShouldPassthroughInsetsBlock(content) {
|
|
3499
|
+
const start = content.indexOf(" if (shouldPassthroughInsets) {");
|
|
3500
|
+
if (start === -1) return null;
|
|
2824
3501
|
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
}
|
|
3502
|
+
const endMarker = "\n\n if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)";
|
|
3503
|
+
const end = content.indexOf(endMarker, start);
|
|
3504
|
+
if (end === -1) return null;
|
|
2829
3505
|
|
|
2830
|
-
|
|
2831
|
-
|
|
3506
|
+
return {
|
|
3507
|
+
start,
|
|
3508
|
+
end,
|
|
3509
|
+
text: content.slice(start, end)
|
|
3510
|
+
};
|
|
3511
|
+
}
|
|
2832
3512
|
|
|
2833
3513
|
// 🚨 ERROR MESSAGE
|
|
2834
3514
|
const ERROR_MSG = `
|
|
@@ -2857,30 +3537,38 @@ function patchFile() {
|
|
|
2857
3537
|
process.exit(1);
|
|
2858
3538
|
}
|
|
2859
3539
|
|
|
3540
|
+
const capacitorConfig = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
3541
|
+
if (capacitorConfig.plugins?.SystemBars?.insetsHandling === "disable") {
|
|
3542
|
+
console.log('ℹ️ SystemBars.insetsHandling is "disable"; skipping SystemBars.java keyboard inset patch.');
|
|
3543
|
+
return;
|
|
3544
|
+
}
|
|
3545
|
+
|
|
2860
3546
|
let content = fs.readFileSync(filePath, "utf8");
|
|
2861
3547
|
|
|
2862
3548
|
// ✅ Already patched?
|
|
2863
|
-
if (content.includes("🔴 ORIGINAL CODE (COMMENTED FOR SAFETY)")) {
|
|
3549
|
+
if (content.includes(SYSTEM_BARS_PATCH_MARKER) || content.includes("🔴 ORIGINAL CODE (COMMENTED FOR SAFETY)")) {
|
|
2864
3550
|
console.log("✅ Already SystemBars.java patched. Skipping...");
|
|
2865
3551
|
return;
|
|
2866
3552
|
}
|
|
2867
3553
|
|
|
2868
|
-
|
|
2869
|
-
if (!
|
|
3554
|
+
const block = findShouldPassthroughInsetsBlock(content);
|
|
3555
|
+
if (!block) {
|
|
2870
3556
|
console.error(ERROR_MSG);
|
|
2871
3557
|
process.exit(1);
|
|
2872
3558
|
}
|
|
2873
3559
|
|
|
2874
3560
|
// 🔁 Replace
|
|
2875
|
-
const updated =
|
|
3561
|
+
const updated =
|
|
3562
|
+
content.slice(0, block.start) +
|
|
3563
|
+
getSystemBarsPatchedBlock(block.text, content) +
|
|
3564
|
+
content.slice(block.end);
|
|
2876
3565
|
|
|
2877
3566
|
fs.writeFileSync(filePath, updated, "utf8");
|
|
2878
3567
|
|
|
2879
|
-
console.log("✅ SystemBars.java patched
|
|
3568
|
+
console.log("✅ SystemBars.java patched with Codeplay keyboard inset fix!");
|
|
2880
3569
|
}
|
|
2881
3570
|
|
|
2882
3571
|
//patchFile();
|
|
2883
|
-
//console.log("SystemBars.java Not Patched, due to upgrade from @capacitor/android:8.4.2. We need to validate if any problem related to the systembar issue. Note: For this we have disable the 'patchFile()' method");
|
|
2884
3572
|
|
|
2885
3573
|
//################################## SystemBars.java update for "@capacitor/android": "^8.3.0" plugin END ###############################
|
|
2886
3574
|
|