codeplay-common 4.0.7 → 4.0.9

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.
@@ -272,68 +272,68 @@ 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
-
326
- const checkAppUniqueId=()=>{
327
-
328
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
329
- const analyticsFlagsUpdated = ensureAnalyticsFlagsInConfig(config);
330
-
331
- const appUniqueId = config.android?.APP_UNIQUE_ID;
332
- const RESIZEABLE_ACTIVITY = config.android?.RESIZEABLE_ACTIVITY;
333
- const orientation = config.android?.ORIENTATION;
334
-
335
-
336
- let logErrorMessage="";
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
+
326
+ const checkAppUniqueId=()=>{
327
+
328
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
329
+ const analyticsFlagsUpdated = ensureAnalyticsFlagsInConfig(config);
330
+
331
+ const appUniqueId = config.android?.APP_UNIQUE_ID;
332
+ const RESIZEABLE_ACTIVITY = config.android?.RESIZEABLE_ACTIVITY;
333
+ const orientation = config.android?.ORIENTATION;
334
+
335
+
336
+ let logErrorMessage="";
337
337
 
338
338
  // 1️⃣ Check if it’s missing
339
339
  if (RESIZEABLE_ACTIVITY === undefined) {
@@ -361,30 +361,30 @@ const checkAppUniqueId=()=>{
361
361
  logErrorMessage+='❌ APP_UNIQUE_ID is missing in capacitor.config.json.';
362
362
  }
363
363
 
364
- else if (!Number.isInteger(appUniqueId)) {
365
- logErrorMessage+='❌ APP_UNIQUE_ID must be an integer. Example: 1, 2, 3, etc.';
366
- }
367
-
368
- if(logErrorMessage!="")
369
- {
370
- if (analyticsFlagsUpdated) {
371
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
372
- console.log('✅ capacitor.config.json analytics flags synced.');
373
- }
374
-
375
- console.error(logErrorMessage);
376
- process.exit(1)
377
- }
378
-
379
- if (analyticsFlagsUpdated) {
380
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
381
- console.log('✅ capacitor.config.json analytics flags synced.');
382
- }
383
-
384
-
385
- console.log(`✅ APP_UNIQUE_ID is valid: ${appUniqueId}`);
386
-
387
- }
364
+ else if (!Number.isInteger(appUniqueId)) {
365
+ logErrorMessage+='❌ APP_UNIQUE_ID must be an integer. Example: 1, 2, 3, etc.';
366
+ }
367
+
368
+ if(logErrorMessage!="")
369
+ {
370
+ if (analyticsFlagsUpdated) {
371
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
372
+ console.log('✅ capacitor.config.json analytics flags synced.');
373
+ }
374
+
375
+ console.error(logErrorMessage);
376
+ process.exit(1)
377
+ }
378
+
379
+ if (analyticsFlagsUpdated) {
380
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
381
+ console.log('✅ capacitor.config.json analytics flags synced.');
382
+ }
383
+
384
+
385
+ console.log(`✅ APP_UNIQUE_ID is valid: ${appUniqueId}`);
386
+
387
+ }
388
388
 
389
389
  checkAppUniqueId();
390
390
 
@@ -2516,7 +2516,7 @@ const checkAndupdateDropInViteConfig = () => {
2516
2516
  console.log("✅ vite.config.(m)js Updated successfully.");
2517
2517
  };
2518
2518
 
2519
- const syncAdmobAliasInViteConfig = () => {
2519
+ const syncAdmobAliasInViteConfig = () => {
2520
2520
  const possibleFiles = [
2521
2521
  "vite.config.mjs",
2522
2522
  "vite.config.js"
@@ -2577,607 +2577,632 @@ const syncAdmobAliasInViteConfig = () => {
2577
2577
  viteContent = viteContent.replace(aliasLineRegex, nextGenAliasLine);
2578
2578
  fs.writeFileSync(viteConfigPath, viteContent, "utf8");
2579
2579
  console.log(`✅ @admob alias updated to ${nextGenRelativePath}`);
2580
- };
2581
-
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
-
2580
+ };
2581
+
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
2677
  const runNpmCommand = (command) => {
2678
2678
  console.log(`🚀 ${command}`);
2679
2679
  execSync(command, { stdio: "inherit" });
2680
2680
  };
2681
2681
 
2682
- const ensureFirebaseAnalyticsWrapper = (analyticsEnabled) => {
2683
- const analyticsDir = getLatestIapDir();
2684
- const legacyAnalyticsDir = path.join(process.cwd(), "src", "js", "analytics");
2685
- const legacyAnalyticsFile = path.join(legacyAnalyticsDir, "firebase-analytics.js");
2686
-
2687
- if (!analyticsDir) {
2688
- console.warn("⚠️ No IAP-x.x folder found. Skipping Firebase analytics wrapper sync.");
2689
- return null;
2690
- }
2691
-
2692
- const analyticsFile = path.join(analyticsDir, "firebase-analytics.js");
2693
-
2694
- if (!fs.existsSync(analyticsDir)) {
2695
- fs.mkdirSync(analyticsDir, { recursive: true });
2696
- }
2697
-
2698
- const activeWrapper = `import { Capacitor, registerPlugin } from '@capacitor/core';
2699
-
2700
- const FirebaseAnalytics = registerPlugin('FirebaseAnalytics');
2701
-
2702
- const isEnabledValue = (value) => value === true || value === 'true';
2703
-
2704
- const canUseNativeAnalytics = () => {
2705
- if (!Capacitor.isNativePlatform()) return false;
2706
-
2707
- const platform = Capacitor.getPlatform();
2708
-
2709
- if (platform === 'android') {
2710
- return isEnabledValue(import.meta.env.VITE_ANDROID_ANALYTICS_ENABLED);
2711
- }
2712
-
2713
- if (platform === 'ios') {
2714
- return isEnabledValue(import.meta.env.VITE_IOS_ANALYTICS_ENABLED);
2715
- }
2716
-
2717
- return false;
2718
- };
2719
-
2720
- const cleanParams = (params = {}) => {
2721
- return Object.entries(params).reduce((result, [key, value]) => {
2722
- if (value === undefined || value === null || value === '') return result;
2723
- if (typeof value === 'number' && Number.isNaN(value)) return result;
2724
-
2725
- result[key] = value;
2726
- return result;
2727
- }, {});
2728
- };
2729
-
2730
- const trackEvent = async (name, params = {}) => {
2731
- if (!canUseNativeAnalytics()) return;
2732
-
2733
- try {
2734
- await FirebaseAnalytics.logEvent({
2735
- name,
2736
- params: cleanParams(params),
2737
- });
2738
- } catch (err) {
2739
- console.warn(\`Firebase analytics event failed: \${name}\`, err);
2740
- }
2741
- };
2742
-
2743
- export const trackSubscriptionScreenViewed = (params) => {
2744
- trackEvent('subscription_screen_view', params);
2745
- };
2746
-
2747
- export const trackSubscriptionCheckoutStarted = (params) => {
2748
- trackEvent('subscription_checkout_start', params);
2749
- };
2750
-
2751
- export const trackSubscriptionPurchased = (params) => {
2752
- trackEvent('subscription_purchase', params);
2753
- };
2754
-
2755
- export const trackConsumablePurchased = (params) => {
2756
- trackEvent('consumable_purchase', params);
2757
- };
2758
- `;
2759
-
2760
- const noopWrapper = `const trackEvent = () => {};
2761
-
2762
- export const trackSubscriptionScreenViewed = trackEvent;
2763
- export const trackSubscriptionCheckoutStarted = trackEvent;
2764
- export const trackSubscriptionPurchased = trackEvent;
2765
- export const trackConsumablePurchased = trackEvent;
2766
- `;
2767
-
2768
- const nextContent = analyticsEnabled ? activeWrapper : noopWrapper;
2769
- const currentContent = fs.existsSync(analyticsFile) ? fs.readFileSync(analyticsFile, "utf8") : "";
2770
-
2771
- if (currentContent !== nextContent) {
2772
- fs.writeFileSync(analyticsFile, nextContent, "utf8");
2773
- console.log(`✅ Firebase analytics wrapper ${analyticsEnabled ? "enabled" : "disabled"}: ${path.relative(process.cwd(), analyticsFile)}`);
2774
- } else {
2775
- console.log(`ℹ️ Firebase analytics wrapper already ${analyticsEnabled ? "enabled" : "disabled"}.`);
2776
- }
2777
-
2778
- if (fs.existsSync(legacyAnalyticsFile)) {
2779
- fs.unlinkSync(legacyAnalyticsFile);
2780
- console.log("✅ Removed old Firebase analytics wrapper: src/js/analytics/firebase-analytics.js");
2781
- }
2782
-
2783
- if (fs.existsSync(legacyAnalyticsDir) && fs.readdirSync(legacyAnalyticsDir).length === 0) {
2784
- fs.rmdirSync(legacyAnalyticsDir);
2785
- }
2786
-
2787
- return analyticsFile;
2788
- };
2789
-
2790
- const syncFirebaseAnalyticsPackages = () => {
2791
- const analyticsConfig = getAnalyticsConfig();
2792
-
2793
- if (analyticsConfig.enabled) {
2794
- if (!isPackageAvailable("@capacitor-firebase/analytics") || !isPackageAvailable("firebase")) {
2795
- runNpmCommand("npm install @capacitor-firebase/analytics firebase");
2796
- } else {
2797
- console.log("ℹ️ Firebase Analytics packages already installed.");
2798
- }
2799
-
2800
- ensureFirebaseAnalyticsWrapper(true);
2801
- return;
2802
- }
2803
-
2804
- const analyticsFile = ensureFirebaseAnalyticsWrapper(false);
2805
-
2806
- if (isPackageAvailable("@capacitor-firebase/analytics")) {
2807
- runNpmCommand("npm uninstall @capacitor-firebase/analytics");
2808
- } else {
2809
- console.log("ℹ️ @capacitor-firebase/analytics is not installed.");
2810
- }
2811
-
2812
- if (isPackageAvailable("firebase")) {
2813
- if (sourceImportsPackage("firebase", analyticsFile)) {
2814
- console.log("ℹ️ Keeping firebase package because other source files import it.");
2815
- } else {
2816
- runNpmCommand("npm uninstall firebase");
2817
- }
2818
- }
2819
- };
2820
-
2821
- const syncFirebaseAnalyticsPodfile = () => {
2822
- const podfilePath = path.join(process.cwd(), "ios", "App", "Podfile");
2823
- if (!fs.existsSync(podfilePath)) return;
2824
-
2825
- const { iosEnabled } = getAnalyticsConfig();
2826
- const basePodLine = " pod 'CapacitorFirebaseAnalytics', :path => '../../node_modules/@capacitor-firebase/analytics'";
2827
- const analyticsPodLine = " pod 'CapacitorFirebaseAnalytics/Analytics', :path => '../../node_modules/@capacitor-firebase/analytics'";
2828
-
2829
- let content = fs.readFileSync(podfilePath, "utf8");
2830
- let nextContent = content;
2831
-
2832
- if (iosEnabled) {
2833
- if (!nextContent.includes(basePodLine)) {
2834
- nextContent = nextContent.replace(
2835
- /(pod 'CapacitorCommunitySafeArea'[^\n]*\r?\n)/,
2836
- `$1${basePodLine}\n`
2837
- );
2838
- }
2839
-
2840
- if (!nextContent.includes(analyticsPodLine)) {
2841
- nextContent = nextContent.replace(
2842
- /(# Add your Pods here\r?\n)/,
2843
- `$1${analyticsPodLine}\n`
2844
- );
2845
- }
2846
- } else {
2847
- nextContent = nextContent
2848
- .split(/\r?\n/)
2849
- .filter(line => !line.includes("CapacitorFirebaseAnalytics"))
2850
- .join("\n");
2851
- }
2852
-
2853
- if (nextContent !== content) {
2854
- fs.writeFileSync(podfilePath, nextContent, "utf8");
2855
- console.log(`✅ iOS Firebase Analytics Podfile entries ${iosEnabled ? "enabled" : "removed"}.`);
2682
+ const syncSystemBarsSafeAreaMigration = () => {
2683
+ if (isPackageAvailable("@capacitor-community/safe-area")) {
2684
+ runNpmCommand("npm uninstall @capacitor-community/safe-area");
2856
2685
  } else {
2857
- console.log(`ℹ️ iOS Firebase Analytics Podfile entries already ${iosEnabled ? "enabled" : "disabled"}.`);
2858
- }
2859
- };
2860
-
2861
- const ensureImportOrRequire = (content, moduleName, esmLine, cjsLine) => {
2862
- const escaped = moduleName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2863
- if (new RegExp(`from\\s*['"]${escaped}['"]|require\\s*\\(\\s*['"]${escaped}['"]\\s*\\)`).test(content)) {
2864
- return content;
2865
- }
2866
-
2867
- const isCommonJs = /module\.exports|require\s*\(/.test(content);
2868
- const line = isCommonJs ? cjsLine : esmLine;
2869
-
2870
- return `${line}\n${content}`;
2871
- };
2872
-
2873
- const ensureViteDefineEntry = (viteContent, key, valueExpression) => {
2874
- const entry = ` '${key}': JSON.stringify(${valueExpression}),`;
2875
-
2876
- if (viteContent.includes(`'${key}'`) || viteContent.includes(`"${key}"`)) {
2877
- return viteContent;
2878
- }
2879
-
2880
- if (/define\s*:\s*{/.test(viteContent)) {
2881
- return viteContent.replace(/define\s*:\s*{\s*/, match => `${match}\n${entry}\n`);
2882
- }
2883
-
2884
- const defineBlock = ` define: {
2885
- '${key}': JSON.stringify(${valueExpression}),
2886
- },`;
2887
-
2888
- if (/\n\s*publicDir\s*:\s*[^,\n]+,?/.test(viteContent)) {
2889
- return viteContent.replace(
2890
- /(\n\s*publicDir\s*:\s*[^,\n]+,?)/,
2891
- `$1\n${defineBlock}`
2892
- );
2686
+ console.log("ℹ️ @capacitor-community/safe-area is not installed.");
2893
2687
  }
2894
2688
 
2895
- return viteContent.replace(
2896
- /(return\s+{)/,
2897
- `$1\n${defineBlock}`
2898
- );
2899
- };
2900
-
2901
- const ensurePrivacyAndAnalyticsViteConfig = () => {
2902
- const viteConfigPath = getViteConfigPath();
2903
-
2904
- if (!viteConfigPath) {
2905
- console.warn("⚠️ No vite config found. Skipping privacy/analytics Vite sync.");
2689
+ if (!fs.existsSync(configPath)) {
2690
+ console.warn("⚠️ capacitor.config.json not found. Skipping SystemBars config sync.");
2906
2691
  return;
2907
2692
  }
2908
2693
 
2909
- let viteContent = fs.readFileSync(viteConfigPath, "utf8");
2910
- const originalContent = viteContent;
2911
-
2912
- viteContent = ensureImportOrRequire(
2913
- viteContent,
2914
- "fs",
2915
- "import fs from 'fs';",
2916
- "const fs = require('fs');"
2917
- );
2918
-
2919
- viteContent = ensureImportOrRequire(
2920
- viteContent,
2921
- "path",
2922
- "import path from 'path';",
2923
- "const path = require('path');"
2924
- );
2925
-
2926
- if (!/\bcapacitorConfig\b/.test(viteContent)) {
2927
- viteContent = viteContent.replace(
2928
- /(\r?\nexport\s+default|\r?\nmodule\.exports)/,
2929
- `\nconst capacitorConfig = JSON.parse(fs.readFileSync(path.resolve(__dirname, './capacitor.config.json'), 'utf8'));\n$1`
2930
- );
2931
- }
2932
-
2933
- if (!/\bAPP_UNIQUE_ID\b/.test(viteContent)) {
2934
- viteContent = viteContent.replace(
2935
- /(const capacitorConfig = JSON\.parse\(fs\.readFileSync\(path\.resolve\(__dirname,\s*['"]\.\/capacitor\.config\.json['"]\),\s*['"]utf8['"]\)\);\r?\n)/,
2936
- `$1const APP_UNIQUE_ID = capacitorConfig.android?.APP_UNIQUE_ID ?? '';\n`
2937
- );
2938
- }
2939
-
2940
- if (!/\bANDROID_ANALYTICS_ENABLED\b/.test(viteContent)) {
2941
- viteContent = viteContent.replace(
2942
- /(const APP_UNIQUE_ID = capacitorConfig\.android\?\.APP_UNIQUE_ID \?\? ['"]['"];\r?\n)/,
2943
- `$1const ANDROID_ANALYTICS_ENABLED = capacitorConfig.android?.ANALYTICS_ENABLED ?? false;\n`
2944
- );
2945
- }
2946
-
2947
- if (!/\bIOS_ANALYTICS_ENABLED\b/.test(viteContent)) {
2948
- viteContent = viteContent.replace(
2949
- /(const ANDROID_ANALYTICS_ENABLED = capacitorConfig\.android\?\.ANALYTICS_ENABLED \?\? false;\r?\n)/,
2950
- `$1const IOS_ANALYTICS_ENABLED = capacitorConfig.ios?.ANALYTICS_ENABLED ?? false;\n`
2951
- );
2952
- }
2953
-
2954
- if (!/\bIAP_DESIGN\b/.test(viteContent)) {
2955
- viteContent = viteContent.replace(
2956
- /(const IOS_ANALYTICS_ENABLED = capacitorConfig\.ios\?\.ANALYTICS_ENABLED \?\? false;\r?\n)/,
2957
- `$1const IAP_DESIGN = capacitorConfig["IAP-Design"] ?? 'default';\n`
2958
- );
2959
- }
2960
-
2961
- viteContent = viteContent
2962
- .replace(
2963
- /const ANDROID_ANALYTICS_ENABLED = capacitorConfig\.android\?\.ANALY[ST]ICS_ENABLED \?\? capacitorConfig\.android\?\.ANALYTICS_ENABLED \?\? false;/g,
2964
- "const ANDROID_ANALYTICS_ENABLED = capacitorConfig.android?.ANALYTICS_ENABLED ?? false;"
2965
- )
2966
- .replace(
2967
- /const IOS_ANALYTICS_ENABLED = capacitorConfig\.ios\?\.ANALY[ST]ICS_ENABLED \?\? capacitorConfig\.ios\?\.ANALYTICS_ENABLED \?\? false;/g,
2968
- "const IOS_ANALYTICS_ENABLED = capacitorConfig.ios?.ANALYTICS_ENABLED ?? false;"
2969
- );
2970
-
2971
- viteContent = ensureViteDefineEntry(viteContent, "import.meta.env.VITE_APP_UNIQUE_ID", "APP_UNIQUE_ID");
2972
- viteContent = ensureViteDefineEntry(viteContent, "import.meta.env.VITE_ANDROID_ANALYTICS_ENABLED", "ANDROID_ANALYTICS_ENABLED");
2973
- viteContent = ensureViteDefineEntry(viteContent, "import.meta.env.VITE_IOS_ANALYTICS_ENABLED", "IOS_ANALYTICS_ENABLED");
2974
- viteContent = ensureViteDefineEntry(viteContent, "import.meta.env.VITE_IAP_DESIGN", "IAP_DESIGN");
2694
+ const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
2695
+ if (!config.plugins) config.plugins = {};
2696
+ if (!config.plugins.SystemBars) config.plugins.SystemBars = {};
2975
2697
 
2976
- if (viteContent !== originalContent) {
2977
- fs.writeFileSync(viteConfigPath, viteContent, "utf8");
2978
- console.log("✅ vite.config.(m)js privacy/analytics settings synced.");
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".');
2979
2702
  } else {
2980
- console.log("ℹ️ vite.config.(m)js privacy/analytics settings already synced.");
2703
+ console.log('ℹ️ capacitor.config.json SystemBars.insetsHandling already "css".');
2981
2704
  }
2982
2705
  };
2983
2706
 
2984
- const syncFirebaseAnalyticsSetup = () => {
2985
- syncFirebaseAnalyticsPackages();
2986
- syncFirebaseAnalyticsPodfile();
2987
- ensurePrivacyAndAnalyticsViteConfig();
2988
- };
2989
-
2990
- const getAdmobIapConfigPath = () => {
2991
- const possiblePaths = [
2992
- path.join(process.cwd(), 'src', 'js', 'Ads', 'admob-ad-configuration-nextgen.json'),
2993
- path.join(process.cwd(), 'src', 'js', 'Ads', 'admob-ad-configuration.json')
2994
- ];
2995
-
2996
- return possiblePaths.find(fileExists);
2997
- };
2998
-
2999
- const getAdmobIapConfig = () => {
3000
- const admobIapConfigPath = getAdmobIapConfigPath();
3001
-
3002
- if (!admobIapConfigPath) {
3003
- console.warn("⚠️ No AdMob configuration JSON found. Skipping RevenueCat IAP package sync.");
3004
- return null;
3005
- }
3006
-
3007
- try {
3008
- return JSON.parse(fs.readFileSync(admobIapConfigPath, "utf8"));
3009
- } catch (err) {
3010
- console.error(`❌ Failed to read ${path.relative(process.cwd(), admobIapConfigPath)}`, err);
3011
- process.exit(1);
3012
- }
3013
- };
3014
-
3015
- const isAnyIapStoreEnabled = (iapConfig) => {
3016
- return Boolean(
3017
- iapConfig?.playstore === true ||
3018
- iapConfig?.samsung === true ||
3019
- iapConfig?.amazon === true ||
3020
- iapConfig?.ios === true
3021
- );
3022
- };
3023
-
3024
- const ensureIapDesignInCapacitorConfig = (iapConfig) => {
3025
- if (!isAnyIapStoreEnabled(iapConfig)) return;
3026
-
3027
- if (!fs.existsSync(configPath)) {
3028
- console.warn("⚠️ capacitor.config.json not found. Skipping IAP-Design sync.");
3029
- return;
3030
- }
3031
-
3032
- const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
3033
-
3034
- if (Object.prototype.hasOwnProperty.call(config, "IAP-Design")) {
3035
- console.log("ℹ️ capacitor.config.json IAP-Design already configured.");
3036
- return;
3037
- }
3038
-
3039
- config["IAP-Design"] = "default";
3040
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
3041
- console.log('✅ Added "IAP-Design": "default" to capacitor.config.json.');
3042
- };
3043
-
3044
- const getCurrentStoreId = () => {
3045
- const envStoreId = Number(process.env.VITE_STORE_ID);
3046
- if (Number.isInteger(envStoreId) && envStoreId > 0) return envStoreId;
3047
-
3048
- const viteConfigPath = getViteConfigPath();
3049
- if (!viteConfigPath) return 1;
3050
-
3051
- const viteConfigContent = fs.readFileSync(viteConfigPath, "utf8");
3052
- const commonAliasMatch = viteConfigContent.match(/['"]@common['"]:\s*path\.resolve\(__dirname,\s*['"]([^'"]+)['"]\)/);
3053
-
3054
- if (!commonAliasMatch) return 1;
3055
-
3056
- const commonFilePath = path.resolve(path.dirname(viteConfigPath), commonAliasMatch[1]);
3057
- if (!fs.existsSync(commonFilePath)) return 1;
3058
-
3059
- const commonFileContent = fs.readFileSync(commonFilePath, "utf8");
3060
- const storeIdMatch = commonFileContent.match(/export\s+let\s+_storeid\s*=\s*import\.meta\.env\.VITE_STORE_ID\s*\|\|\s*(\d+)\s*;/);
3061
-
3062
- return storeIdMatch ? Number(storeIdMatch[1]) : 1;
3063
- };
3064
-
3065
- const getRevenueCatStoreState = (iapConfig) => {
3066
- const storeId = getCurrentStoreId();
3067
- const configuration = iapConfig.configuration || {};
3068
- const storeMap = {
3069
- 1: {
3070
- name: "PlayStore",
3071
- enabled: iapConfig.playstore === true,
3072
- apiKeyName: "IAP.configuration.playstore",
3073
- apiKey: configuration.playstore,
3074
- usesGoogleBilling: true
3075
- },
3076
- 6: {
3077
- name: "iOSStore",
3078
- enabled: iapConfig.ios === true,
3079
- apiKeyName: "IAP.configuration.ios",
3080
- apiKey: configuration.ios,
3081
- usesGoogleBilling: false
3082
- },
3083
- 7: {
3084
- name: "AmazonStore",
3085
- enabled: iapConfig.amazon === true,
3086
- apiKeyName: "IAP.configuration.amazon",
3087
- apiKey: configuration.amazon,
3088
- usesGoogleBilling: false
3089
- }
3090
- };
3091
-
3092
- return {
3093
- storeId,
3094
- store: storeMap[storeId] || null
3095
- };
3096
- };
3097
-
3098
- const ensureAndroidPermission = (permission, enabled) => {
3099
- if (!fs.existsSync(androidManifestPath)) return false;
3100
-
3101
- let manifestContent = fs.readFileSync(androidManifestPath, "utf8");
3102
- const permissionLine = ` <uses-permission android:name="${permission}" />`;
3103
- const permissionRegex = new RegExp(`^\\s*<uses-permission\\s+android:name="${permission.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"\\s*/?>\\s*\\r?\\n?`, "m");
3104
-
3105
- if (enabled) {
3106
- if (permissionRegex.test(manifestContent)) return false;
3107
-
3108
- manifestContent = manifestContent.replace(
3109
- /<\/manifest>\s*$/,
3110
- `${permissionLine}\n</manifest>`
3111
- );
3112
- fs.writeFileSync(androidManifestPath, manifestContent, "utf8");
3113
- console.log(`✅ Added Android permission: ${permission}`);
3114
- return true;
3115
- }
3116
-
3117
- if (!permissionRegex.test(manifestContent)) return false;
3118
-
3119
- manifestContent = manifestContent.replace(permissionRegex, "");
3120
- fs.writeFileSync(androidManifestPath, manifestContent, "utf8");
3121
- console.log(`✅ Removed Android permission: ${permission}`);
3122
- return true;
3123
- };
3124
-
3125
- const syncRevenueCatIapSetup = () => {
3126
- const admobConfig = getAdmobIapConfig();
3127
- const iapConfig = admobConfig?.IAP;
3128
-
3129
- if (!iapConfig) {
3130
- console.log("ℹ️ IAP configuration not found. Skipping RevenueCat package sync.");
3131
- return;
3132
- }
3133
-
3134
- ensureIapDesignInCapacitorConfig(iapConfig);
3135
-
3136
- const revenueCatEnabled =
3137
- iapConfig.playstore === true ||
3138
- iapConfig.ios === true ||
3139
- iapConfig.amazon === true;
3140
- const { storeId, store } = getRevenueCatStoreState(iapConfig);
3141
- const revenueCatEnabledForCurrentStore = store?.enabled === true;
3142
-
3143
- if (revenueCatEnabledForCurrentStore && !store.apiKey) {
3144
- console.error(`❌ RevenueCat IAP is enabled for ${store.name} but ${store.apiKeyName} is missing.`);
3145
- process.exit(1);
3146
- }
3147
-
3148
- let packageChanged = false;
3149
-
3150
- if (revenueCatEnabledForCurrentStore) {
3151
- if (!isPackageAvailable("@revenuecat/purchases-capacitor")) {
3152
- runNpmCommand("npm install @revenuecat/purchases-capacitor");
3153
- packageChanged = true;
3154
- } else {
3155
- console.log(`ℹ️ RevenueCat package already installed for ${store.name}.`);
3156
- }
3157
- } else if (isPackageAvailable("@revenuecat/purchases-capacitor")) {
3158
- runNpmCommand("npm uninstall @revenuecat/purchases-capacitor");
3159
- packageChanged = true;
3160
- } else {
3161
- console.log(`ℹ️ RevenueCat package is not required for store id ${storeId}.`);
3162
- }
3163
-
3164
- ensureAndroidPermission("com.android.vending.BILLING", store?.usesGoogleBilling === true && revenueCatEnabledForCurrentStore);
3165
-
3166
- if (iapConfig.samsung === true && revenueCatEnabled) {
3167
- console.warn("⚠️ Samsung IAP uses cordova-plugin-samsungiap; PlayStore/Amazon/iOS use RevenueCat.");
3168
- }
3169
-
3170
- if (packageChanged) {
3171
- runNpmCommand("npx cap sync");
3172
- }
3173
- };
3174
-
3175
-
3176
-
3177
-
3178
-
3179
-
3180
-
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
+
3200
+
3201
+
3202
+
3203
+
3204
+
3205
+
3181
3206
 
3182
3207
 
3183
3208
  const compareVersion = (v1, v2) => {
@@ -3344,17 +3369,18 @@ ensureGitignoreEntry('buildCodeplay/');
3344
3369
 
3345
3370
 
3346
3371
  // Run the validation
3347
- (async () => {
3372
+ (async () => {
3348
3373
 
3349
3374
  await loadPluginVersions(); // 🔥 NEW
3350
3375
 
3376
+ syncSystemBarsSafeAreaMigration();
3351
3377
  await checkPlugins();
3352
3378
  syncRevenueCatIapSetup();
3353
3379
  syncFirebaseAnalyticsSetup();
3354
- checkAndupdateDropInViteConfig();
3355
- syncAdmobAliasInViteConfig();
3356
- checkAdmobConfigurationProperty()
3357
- })();
3380
+ checkAndupdateDropInViteConfig();
3381
+ syncAdmobAliasInViteConfig();
3382
+ checkAdmobConfigurationProperty()
3383
+ })();
3358
3384
 
3359
3385
 
3360
3386
  // ======================================================
@@ -3444,45 +3470,45 @@ const filePath = path.join(
3444
3470
  "../node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java"
3445
3471
  );
3446
3472
 
3447
- // 🔍 OLD BLOCK (anchor)
3448
- const OLD_BLOCK = `if (shouldPassthroughInsets) {
3449
- // We need to correct for a possible shown IME
3450
- v.setPadding(0, 0, 0, keyboardVisible ? imeInsets.bottom : 0);
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);
3451
3488
 
3452
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && hasViewportCover && insetHandlingEnabled) {
3489
+ if (${safeAreaCondition}) {
3453
3490
  Insets safeAreaInsets = calcSafeAreaInsets(insets);
3454
3491
  injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left);
3455
3492
  }
3456
3493
 
3457
- return new WindowInsetsCompat.Builder(insets)
3458
- .setInsets(
3459
- WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout(),
3460
- Insets.of(
3461
- systemBarsInsets.left,
3462
- systemBarsInsets.top,
3463
- systemBarsInsets.right,
3464
- getBottomInset(systemBarsInsets, keyboardVisible)
3465
- )
3466
- )
3467
- .build();
3494
+ return insets; // WebView handles keyboard and safe-area sizing.
3468
3495
  }`;
3496
+ }
3469
3497
 
3470
- // NEW BLOCK
3471
- const NEW_BLOCK = `if (shouldPassthroughInsets) {
3472
- /* 🔴 ORIGINAL CODE (COMMENTED FOR SAFETY)
3473
- ${OLD_BLOCK.split("\n").map(line => " " + line).join("\n")}
3474
- */
3475
-
3476
- // ✅ NEW LOGIC (CUSTOM FIX)
3477
- v.setPadding(0, 0, 0, 0);
3498
+ function findShouldPassthroughInsetsBlock(content) {
3499
+ const start = content.indexOf(" if (shouldPassthroughInsets) {");
3500
+ if (start === -1) return null;
3478
3501
 
3479
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && hasViewportCover && insetHandlingEnabled) {
3480
- Insets safeAreaInsets = calcSafeAreaInsets(insets);
3481
- injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left);
3482
- }
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;
3483
3505
 
3484
- return insets; // WebView handles everything
3485
- }`;
3506
+ return {
3507
+ start,
3508
+ end,
3509
+ text: content.slice(start, end)
3510
+ };
3511
+ }
3486
3512
 
3487
3513
  // 🚨 ERROR MESSAGE
3488
3514
  const ERROR_MSG = `
@@ -3511,30 +3537,38 @@ function patchFile() {
3511
3537
  process.exit(1);
3512
3538
  }
3513
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
+
3514
3546
  let content = fs.readFileSync(filePath, "utf8");
3515
3547
 
3516
3548
  // ✅ Already patched?
3517
- if (content.includes("🔴 ORIGINAL CODE (COMMENTED FOR SAFETY)")) {
3549
+ if (content.includes(SYSTEM_BARS_PATCH_MARKER) || content.includes("🔴 ORIGINAL CODE (COMMENTED FOR SAFETY)")) {
3518
3550
  console.log("✅ Already SystemBars.java patched. Skipping...");
3519
3551
  return;
3520
3552
  }
3521
3553
 
3522
- // 🔍 Check old block exists
3523
- if (!content.includes(OLD_BLOCK)) {
3554
+ const block = findShouldPassthroughInsetsBlock(content);
3555
+ if (!block) {
3524
3556
  console.error(ERROR_MSG);
3525
3557
  process.exit(1);
3526
3558
  }
3527
3559
 
3528
3560
  // 🔁 Replace
3529
- const updated = content.replace(OLD_BLOCK, NEW_BLOCK);
3561
+ const updated =
3562
+ content.slice(0, block.start) +
3563
+ getSystemBarsPatchedBlock(block.text, content) +
3564
+ content.slice(block.end);
3530
3565
 
3531
3566
  fs.writeFileSync(filePath, updated, "utf8");
3532
3567
 
3533
- console.log("✅ SystemBars.java patched (comment + new logic)!");
3568
+ console.log("✅ SystemBars.java patched with Codeplay keyboard inset fix!");
3534
3569
  }
3535
3570
 
3536
3571
  //patchFile();
3537
- //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");
3538
3572
 
3539
3573
  //################################## SystemBars.java update for "@capacitor/android": "^8.3.0" plugin END ###############################
3540
3574