codeplay-common 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/files/.env.storeid1 +1 -0
- package/files/.env.storeid2 +1 -0
- package/files/.env.storeid7 +1 -0
- package/files/add-splash-screen-1.0.js +77 -0
- package/files/codeplayBeforeBuild-1.0.js +139 -0
- package/files/finalrelease13 +493 -0
- package/files/iap-install-1.js +146 -0
- package/files/ionic.config.json +7 -0
- package/files/modify-plugin-xml.js +36 -0
- package/files/setSplashAnimation-1.0.js +167 -0
- package/files/splashxml/codeplay_splashScreen.xml +11 -0
- package/package.json +15 -0
- package/scripts/sync-files.js +67 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VITE_STORE_ID=1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VITE_STORE_ID=2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VITE_STORE_ID=7
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
// Define file paths
|
|
5
|
+
const projectFolder = path.resolve(".");
|
|
6
|
+
const sourceSplashIcon = path.join(projectFolder, "resources", "splash_icon.png");
|
|
7
|
+
const destinationSplashIcon = path.join(
|
|
8
|
+
projectFolder,
|
|
9
|
+
"android",
|
|
10
|
+
"app",
|
|
11
|
+
"src",
|
|
12
|
+
"main",
|
|
13
|
+
"res",
|
|
14
|
+
"drawable-nodpi",
|
|
15
|
+
"splash_icon.png"
|
|
16
|
+
);
|
|
17
|
+
const sourceSplashXML = path.join(projectFolder, "splashxml", "codeplay_splashScreen.xml");
|
|
18
|
+
const destinationSplashXML = path.join(
|
|
19
|
+
projectFolder,
|
|
20
|
+
"android",
|
|
21
|
+
"app",
|
|
22
|
+
"src",
|
|
23
|
+
"main",
|
|
24
|
+
"res",
|
|
25
|
+
"values",
|
|
26
|
+
"codeplay_splashScreen.xml"
|
|
27
|
+
);
|
|
28
|
+
const androidManifestPath = path.join(
|
|
29
|
+
projectFolder,
|
|
30
|
+
"android",
|
|
31
|
+
"app",
|
|
32
|
+
"src",
|
|
33
|
+
"main",
|
|
34
|
+
"AndroidManifest.xml"
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
// Helper function to copy files
|
|
38
|
+
function copyFile(source, destination) {
|
|
39
|
+
if (!fs.existsSync(source)) {
|
|
40
|
+
throw new Error(`Source file not found: ${source}`);
|
|
41
|
+
}
|
|
42
|
+
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
|
43
|
+
fs.copyFileSync(source, destination);
|
|
44
|
+
console.log(`Copied: ${source} -> ${destination}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Helper function to update AndroidManifest.xml
|
|
48
|
+
function updateAndroidManifest() {
|
|
49
|
+
if (!fs.existsSync(androidManifestPath)) {
|
|
50
|
+
throw new Error(`AndroidManifest.xml not found: ${androidManifestPath}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let manifestContent = fs.readFileSync(androidManifestPath, "utf-8");
|
|
54
|
+
|
|
55
|
+
// Replace the android:theme attribute in the <activity> tag
|
|
56
|
+
manifestContent = manifestContent.replace(
|
|
57
|
+
/<activity[^>]*android:theme="[^"]*"/,
|
|
58
|
+
(match) => {
|
|
59
|
+
return match.replace(/android:theme="[^"]*"/, 'android:theme="@style/Theme.Codeplay.SplashScreen"');
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
fs.writeFileSync(androidManifestPath, manifestContent, "utf-8");
|
|
64
|
+
console.log(`Updated AndroidManifest.xml with new theme.`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Perform the tasks
|
|
68
|
+
try {
|
|
69
|
+
console.log("Starting splash screen setup...");
|
|
70
|
+
copyFile(sourceSplashIcon, destinationSplashIcon);
|
|
71
|
+
copyFile(sourceSplashXML, destinationSplashXML);
|
|
72
|
+
updateAndroidManifest();
|
|
73
|
+
console.log("Splash screen setup completed.");
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error(`Error: ${error.message}`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const plist = require('plist');
|
|
4
|
+
|
|
5
|
+
const configPath = path.join(process.cwd(), 'capacitor.config.json');
|
|
6
|
+
const androidPlatformPath = path.join(process.cwd(), 'android');
|
|
7
|
+
const iosPlatformPath = path.join(process.cwd(), 'ios');
|
|
8
|
+
const pluginPath = path.join(process.cwd(), 'node_modules', 'emi-indo-cordova-plugin-admob', 'plugin.xml');
|
|
9
|
+
const infoPlistPath = path.join(process.cwd(), 'ios', 'App', 'App', 'Info.plist');
|
|
10
|
+
|
|
11
|
+
function fileExists(filePath) {
|
|
12
|
+
return fs.existsSync(filePath);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getAdMobConfig() {
|
|
16
|
+
if (!fileExists(configPath)) {
|
|
17
|
+
throw new Error('capacitor.config.json not found. Ensure this is a Capacitor project.');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
21
|
+
const admobConfig = config.plugins?.AdMob;
|
|
22
|
+
|
|
23
|
+
if (!admobConfig || !admobConfig.APP_ID_ANDROID || !admobConfig.APP_ID_IOS) {
|
|
24
|
+
throw new Error('AdMob configuration is missing in capacitor.config.json. Ensure APP_ID_ANDROID and APP_ID_IOS are defined.');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
APP_ID_ANDROID: admobConfig.APP_ID_ANDROID,
|
|
29
|
+
APP_ID_IOS: admobConfig.APP_ID_IOS,
|
|
30
|
+
USE_LITE_ADS: admobConfig.USE_LITE_ADS === "lite",
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function updatePluginXml(admobConfig) {
|
|
35
|
+
if (!fileExists(pluginPath)) {
|
|
36
|
+
console.error('plugin.xml not found. Ensure the plugin is installed.');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let pluginContent = fs.readFileSync(pluginPath, 'utf8');
|
|
41
|
+
|
|
42
|
+
pluginContent = pluginContent
|
|
43
|
+
.replace(/<preference name="APP_ID_ANDROID" default=".*?" \/>/, `<preference name="APP_ID_ANDROID" default="${admobConfig.APP_ID_ANDROID}" />`)
|
|
44
|
+
.replace(/<preference name="APP_ID_IOS" default=".*?" \/>/, `<preference name="APP_ID_IOS" default="${admobConfig.APP_ID_IOS}" />`);
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
fs.writeFileSync(pluginPath, pluginContent, 'utf8');
|
|
48
|
+
console.log('AdMob IDs successfully updated in plugin.xml');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function updateInfoPlist(admobConfig) {
|
|
52
|
+
if (!fileExists(infoPlistPath)) {
|
|
53
|
+
console.error('Info.plist not found. Ensure you have built the iOS project.');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const plistContent = fs.readFileSync(infoPlistPath, 'utf8');
|
|
58
|
+
const plistData = plist.parse(plistContent);
|
|
59
|
+
|
|
60
|
+
plistData.GADApplicationIdentifier = admobConfig.APP_ID_IOS;
|
|
61
|
+
plistData.NSUserTrackingUsageDescription = 'This identifier will be used to deliver personalized ads to you.';
|
|
62
|
+
plistData.GADDelayAppMeasurementInit = true;
|
|
63
|
+
|
|
64
|
+
// https://developers.google.com/admob/ios/quick-start
|
|
65
|
+
plistData.SKAdNetworkItems = [
|
|
66
|
+
{ SKAdNetworkIdentifier: 'cstr6suwn9.skadnetwork' }, // Google
|
|
67
|
+
{ SKAdNetworkIdentifier: '4fzdc2evr5.skadnetwork' }, // Aarki
|
|
68
|
+
{ SKAdNetworkIdentifier: '2fnua5tdw4.skadnetwork' }, // Adform
|
|
69
|
+
{ SKAdNetworkIdentifier: 'ydx93a7ass.skadnetwork' }, // Adikteev
|
|
70
|
+
{ SKAdNetworkIdentifier: 'p78axxw29g.skadnetwork' }, // Amazon
|
|
71
|
+
{ SKAdNetworkIdentifier: 'v72qych5uu.skadnetwork' }, // Appier
|
|
72
|
+
{ SKAdNetworkIdentifier: 'ludvb6z3bs.skadnetwork' }, // Applovin
|
|
73
|
+
{ SKAdNetworkIdentifier: 'cp8zw746q7.skadnetwork' }, // Arpeely
|
|
74
|
+
{ SKAdNetworkIdentifier: '3sh42y64q3.skadnetwork' }, // Basis
|
|
75
|
+
{ SKAdNetworkIdentifier: 'c6k4g5qg8m.skadnetwork' }, // Beeswax.io
|
|
76
|
+
{ SKAdNetworkIdentifier: 's39g8k73mm.skadnetwork' }, // Bidease
|
|
77
|
+
{ SKAdNetworkIdentifier: '3qy4746246.skadnetwork' }, // Bigabid
|
|
78
|
+
{ SKAdNetworkIdentifier: 'hs6bdukanm.skadnetwork' }, // Criteo
|
|
79
|
+
{ SKAdNetworkIdentifier: 'mlmmfzh3r3.skadnetwork' }, // Digital Turbine DSP
|
|
80
|
+
{ SKAdNetworkIdentifier: 'v4nxqhlyqp.skadnetwork' }, // i-mobile
|
|
81
|
+
{ SKAdNetworkIdentifier: 'wzmmz9fp6w.skadnetwork' }, // InMobi
|
|
82
|
+
{ SKAdNetworkIdentifier: 'su67r6k2v3.skadnetwork' }, // ironSource Ads
|
|
83
|
+
{ SKAdNetworkIdentifier: 'yclnxrl5pm.skadnetwork' }, // Jampp
|
|
84
|
+
{ SKAdNetworkIdentifier: '7ug5zh24hu.skadnetwork' }, // Liftoff
|
|
85
|
+
{ SKAdNetworkIdentifier: 'gta9lk7p23.skadnetwork' }, // Liftoff Monetize
|
|
86
|
+
{ SKAdNetworkIdentifier: 'vutu7akeur.skadnetwork' }, // LINE
|
|
87
|
+
{ SKAdNetworkIdentifier: 'y5ghdn5j9k.skadnetwork' }, // Mediaforce
|
|
88
|
+
{ SKAdNetworkIdentifier: 'v9wttpbfk9.skadnetwork' }, // Meta (1 of 2)
|
|
89
|
+
{ SKAdNetworkIdentifier: 'n38lu8286q.skadnetwork' }, // Meta (2 of 2)
|
|
90
|
+
{ SKAdNetworkIdentifier: '47vhws6wlr.skadnetwork' }, // MicroAd
|
|
91
|
+
{ SKAdNetworkIdentifier: 'kbd757ywx3.skadnetwork' }, // Mintegral / Mobvista
|
|
92
|
+
{ SKAdNetworkIdentifier: '9t245vhmpl.skadnetwork' }, // Moloco
|
|
93
|
+
{ SKAdNetworkIdentifier: 'a2p9lx4jpn.skadnetwork' }, // Opera
|
|
94
|
+
{ SKAdNetworkIdentifier: '22mmun2rn5.skadnetwork' }, // Pangle
|
|
95
|
+
{ SKAdNetworkIdentifier: '4468km3ulz.skadnetwork' }, // Realtime Technologies GmbH
|
|
96
|
+
{ SKAdNetworkIdentifier: '2u9pt9hc89.skadnetwork' }, // Remerge
|
|
97
|
+
{ SKAdNetworkIdentifier: '8s468mfl3y.skadnetwork' }, // RTB House
|
|
98
|
+
{ SKAdNetworkIdentifier: 'ppxm28t8ap.skadnetwork' }, // Smadex
|
|
99
|
+
{ SKAdNetworkIdentifier: 'uw77j35x4d.skadnetwork' }, // The Trade Desk
|
|
100
|
+
{ SKAdNetworkIdentifier: 'pwa73g5rt2.skadnetwork' }, // Tremor
|
|
101
|
+
{ SKAdNetworkIdentifier: '578prtvx9j.skadnetwork' }, // Unicorn
|
|
102
|
+
{ SKAdNetworkIdentifier: '4dzt52r2t5.skadnetwork' }, // Unity Ads
|
|
103
|
+
{ SKAdNetworkIdentifier: 'tl55sbb4fm.skadnetwork' }, // Verve
|
|
104
|
+
{ SKAdNetworkIdentifier: 'e5fvkxwrpn.skadnetwork' }, // Yahoo!
|
|
105
|
+
{ SKAdNetworkIdentifier: '8c4e2ghe7u.skadnetwork' }, // Yahoo! Japan Ads
|
|
106
|
+
{ SKAdNetworkIdentifier: '3rd42ekr43.skadnetwork' }, // YouAppi
|
|
107
|
+
{ SKAdNetworkIdentifier: '3qcr597p9d.skadnetwork' }, // Zucks
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
const updatedPlistContent = plist.build(plistData);
|
|
111
|
+
fs.writeFileSync(infoPlistPath, updatedPlistContent, 'utf8');
|
|
112
|
+
console.log('AdMob IDs and additional configurations successfully updated in Info.plist');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
if (!fileExists(configPath)) {
|
|
117
|
+
throw new Error('capacitor.config.json not found. Skipping setup.');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!fileExists(androidPlatformPath) && !fileExists(iosPlatformPath)) {
|
|
121
|
+
throw new Error('Neither Android nor iOS platforms are found. Ensure platforms are added to your Capacitor project.');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const admobConfig = getAdMobConfig();
|
|
125
|
+
|
|
126
|
+
if (fileExists(androidPlatformPath)) {
|
|
127
|
+
updatePluginXml(admobConfig);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (fileExists(iosPlatformPath)) {
|
|
131
|
+
updateInfoPlist(admobConfig);
|
|
132
|
+
}
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error(error.message);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const child_process = require('child_process');
|
|
4
|
+
const readline = require('readline');
|
|
5
|
+
|
|
6
|
+
// Define a mapping between store IDs and store names
|
|
7
|
+
const storeNames = {
|
|
8
|
+
"1": "PlayStore",
|
|
9
|
+
"2": "SamsungStore",
|
|
10
|
+
"7": "AmazonStore"
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const androidManifestPath = path.join("android", "app", "src", "main", "AndroidManifest.xml");
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
const admobConfigPath = path.join('src', 'js','Ads', 'admob-ad-configuration.json');
|
|
18
|
+
let admobConfig;
|
|
19
|
+
try {
|
|
20
|
+
admobConfig = JSON.parse(fs.readFileSync(admobConfigPath, 'utf8'));
|
|
21
|
+
} catch (err) {
|
|
22
|
+
console.error("Failed to read admob-ad-configuration.json", err);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
const checkCommonFileStoreId=()=>{
|
|
30
|
+
const possibleConfigFiles = ['vite.config.mjs', 'vite.config.js'];
|
|
31
|
+
let viteConfigPath;
|
|
32
|
+
for (const configFile of possibleConfigFiles) {
|
|
33
|
+
const fullPath = path.resolve( configFile);
|
|
34
|
+
if (fs.existsSync(fullPath)) {
|
|
35
|
+
viteConfigPath = fullPath;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!viteConfigPath) {
|
|
41
|
+
console.error('Error: No vite.config.mjs or vite.config.js file found.');
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
// Read vite config file
|
|
47
|
+
const viteConfigContent = fs.readFileSync(viteConfigPath, 'utf-8');
|
|
48
|
+
|
|
49
|
+
// Extract @common alias path
|
|
50
|
+
const aliasPattern = /'@common':\s*path\.resolve\(__dirname,\s*'(.+?)'\)/;
|
|
51
|
+
const match = viteConfigContent.match(aliasPattern);
|
|
52
|
+
|
|
53
|
+
if (!match) {
|
|
54
|
+
console.error(`Error: @common alias not found in ${viteConfigPath}`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const commonFilePath = match[1];
|
|
59
|
+
const resolvedCommonPath = path.resolve(__dirname, commonFilePath);
|
|
60
|
+
|
|
61
|
+
// Read the common file content
|
|
62
|
+
if (!fs.existsSync(resolvedCommonPath)) {
|
|
63
|
+
console.error(`Error: Resolved common file does not exist: ${resolvedCommonPath}`);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const commonFileContent = fs.readFileSync(resolvedCommonPath, 'utf-8');
|
|
68
|
+
|
|
69
|
+
// Check for the _storeid export line
|
|
70
|
+
const storeIdPattern = /export\s+let\s+_storeid\s*=\s*import\.meta\.env\.VITE_STORE_ID\s*\|\|\s*1\s*;/;
|
|
71
|
+
if (!storeIdPattern.test(commonFileContent)) {
|
|
72
|
+
console.error(`Error: _storeid value is wrong in ${commonFilePath}`);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log(commonFilePath,'Success - No problem found');
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error('Error:', error);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const checkIsTestingInAdmob=()=>{
|
|
85
|
+
|
|
86
|
+
if (admobConfig.config && admobConfig.config.isTesting === true) {
|
|
87
|
+
console.error(`Problem found while generating the AAB file. Please change "isTesting: true" to "isTesting: false" in the "admob-ad-configuration.json" file.`);
|
|
88
|
+
process.exit(1); // Exit with an error code to halt the process
|
|
89
|
+
} else {
|
|
90
|
+
console.log('No problem found. "isTesting" is either already false or not defined.');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const addPermission_AD_ID=()=>{
|
|
95
|
+
|
|
96
|
+
const admobPluginXmlPath = path.join('node_modules', 'emi-indo-cordova-plugin-admob', 'plugin.xml');
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
fs.access(admobPluginXmlPath, fs.constants.F_OK, (err) => {
|
|
100
|
+
if (err) {
|
|
101
|
+
isAdmobFound = false;
|
|
102
|
+
} else {
|
|
103
|
+
isAdmobFound = true;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
if (isAdmobFound) {
|
|
109
|
+
// Check if AndroidManifest.xml exists
|
|
110
|
+
if (fs.existsSync(androidManifestPath)) {
|
|
111
|
+
// Read the content of AndroidManifest.xml
|
|
112
|
+
let manifestContent = fs.readFileSync(androidManifestPath, 'utf8');
|
|
113
|
+
|
|
114
|
+
// Check if the ad_id permission already exists
|
|
115
|
+
const adIdPermission = '<uses-permission android:name="com.google.android.gms.permission.AD_ID" />';
|
|
116
|
+
if (!manifestContent.includes(adIdPermission)) {
|
|
117
|
+
console.log("ad_id permission not found. Adding to AndroidManifest.xml.");
|
|
118
|
+
|
|
119
|
+
// Add the ad_id permission before the closing </manifest> tag
|
|
120
|
+
manifestContent = manifestContent.replace('</manifest>', ` ${adIdPermission}\n</manifest>`);
|
|
121
|
+
|
|
122
|
+
// Write the updated manifest content back to AndroidManifest.xml
|
|
123
|
+
fs.writeFileSync(androidManifestPath, manifestContent, 'utf8');
|
|
124
|
+
console.log("ad_id permission added successfully.");
|
|
125
|
+
} else {
|
|
126
|
+
console.log("ad_id permission already exists in AndroidManifest.xml.");
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
console.error("AndroidManifest.xml not found at the specified path.");
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
console.log("\x1b[33m%s\x1b[0m", "No admob found, so permission.AD_ID is not added");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
checkCommonFileStoreId();
|
|
138
|
+
checkIsTestingInAdmob();
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
let isAdmobFound = true;
|
|
142
|
+
addPermission_AD_ID()
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
const { playstore, samsung, amazon } = admobConfig.IAP;
|
|
147
|
+
console.log(`IAP Configurations - PlayStore: ${playstore}, Samsung: ${samsung}, Amazon: ${amazon}`);
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
// Get the store ID from the command line arguments
|
|
155
|
+
const storeIdArg = process.argv[2]; // Get the store ID from the command line
|
|
156
|
+
const storeIds = storeIdArg ? [storeIdArg] : ["1", "2", "7"]; // If a specific ID is provided, use it; otherwise, use all store IDs
|
|
157
|
+
|
|
158
|
+
// Store the original minSdkVersion globally
|
|
159
|
+
let originalMinSdkVersion;
|
|
160
|
+
|
|
161
|
+
// Remove any existing AAB files before starting the build process
|
|
162
|
+
const aabDirectory = path.join("android", "app", "build", "outputs", "bundle", "release");
|
|
163
|
+
if (fs.existsSync(aabDirectory)) {
|
|
164
|
+
const files = fs.readdirSync(aabDirectory).filter(file => file.endsWith('.aab'));
|
|
165
|
+
files.forEach(file => {
|
|
166
|
+
const filePath = path.join(aabDirectory, file);
|
|
167
|
+
fs.unlinkSync(filePath);
|
|
168
|
+
console.log(`Deleted existing AAB file: ${file}`);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const aabOutputDir = path.join("AAB");
|
|
173
|
+
if (!fs.existsSync(aabOutputDir)) {
|
|
174
|
+
fs.mkdirSync(aabOutputDir);
|
|
175
|
+
console.log(`Created directory: ${aabOutputDir}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (fs.existsSync(aabOutputDir)) {
|
|
179
|
+
const files = fs.readdirSync(aabOutputDir).filter(file => file.endsWith('.aab'));
|
|
180
|
+
files.forEach(file => {
|
|
181
|
+
const filePath = path.join(aabOutputDir, file);
|
|
182
|
+
fs.unlinkSync(filePath);
|
|
183
|
+
console.log(`Deleted existing AAB file: ${file}`);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
// Extract version code and version name from build.gradle
|
|
189
|
+
const gradleFilePath = path.join("android", "app", "build.gradle");
|
|
190
|
+
const gradleContent = fs.readFileSync(gradleFilePath, 'utf8');
|
|
191
|
+
|
|
192
|
+
const versionCodeMatch = gradleContent.match(/versionCode\s+(\d+)/);
|
|
193
|
+
const versionNameMatch = gradleContent.match(/versionName\s+"([^"]+)"/);
|
|
194
|
+
|
|
195
|
+
const versionCode = versionCodeMatch ? versionCodeMatch[1] : '';
|
|
196
|
+
const versionName = versionNameMatch ? versionNameMatch[1] : '';
|
|
197
|
+
|
|
198
|
+
// Display the current versionCode and versionName
|
|
199
|
+
console.log(`Current versionCode: ${versionCode}`);
|
|
200
|
+
console.log(`Current versionName: ${versionName}`);
|
|
201
|
+
|
|
202
|
+
// Create an interface for user input
|
|
203
|
+
const rl = readline.createInterface({
|
|
204
|
+
input: process.stdin,
|
|
205
|
+
output: process.stdout
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Ask for new versionCode
|
|
209
|
+
rl.question('Enter new versionCode (press enter to keep current): ', (newVersionCode) => {
|
|
210
|
+
const finalVersionCode = newVersionCode || versionCode; // Use existing if no input
|
|
211
|
+
|
|
212
|
+
// Ask for new versionName
|
|
213
|
+
rl.question('Enter new versionName (press enter to keep current): ', (newVersionName) => {
|
|
214
|
+
const finalVersionName = newVersionName || versionName; // Use existing if no input
|
|
215
|
+
|
|
216
|
+
// Log the final version details
|
|
217
|
+
console.log(`Final versionCode: ${finalVersionCode}`);
|
|
218
|
+
console.log(`Final versionName: ${finalVersionName}`);
|
|
219
|
+
|
|
220
|
+
// Update build.gradle with the new version details
|
|
221
|
+
let updatedGradleContent = gradleContent
|
|
222
|
+
.replace(/versionCode\s+\d+/, `versionCode ${finalVersionCode}`)
|
|
223
|
+
.replace(/versionName\s+"[^"]+"/, `versionName "${finalVersionName}"`);
|
|
224
|
+
|
|
225
|
+
// Check if resConfigs "en" already exists
|
|
226
|
+
const resConfigsLine = ' resConfigs "en"';
|
|
227
|
+
if (!updatedGradleContent.includes(resConfigsLine)) {
|
|
228
|
+
// Add resConfigs "en" below versionName
|
|
229
|
+
updatedGradleContent = updatedGradleContent.replace(/versionName\s+"[^"]+"/, `versionName "${finalVersionName}"\n${resConfigsLine}`);
|
|
230
|
+
} else {
|
|
231
|
+
console.log('resConfigs "en" already exists in build.gradle.');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Write the updated gradle content back to build.gradle
|
|
235
|
+
fs.writeFileSync(gradleFilePath, updatedGradleContent, 'utf8');
|
|
236
|
+
console.log(`Updated build.gradle with versionCode: ${finalVersionCode}, versionName: ${finalVersionName}, and resConfigs "en"`);
|
|
237
|
+
|
|
238
|
+
storeIds.forEach((id) => {
|
|
239
|
+
console.log(`Building for Store ID ${id}`);
|
|
240
|
+
|
|
241
|
+
// Set the environment variable for store ID
|
|
242
|
+
process.env.VITE_STORE_ID = id;
|
|
243
|
+
|
|
244
|
+
// Conditionally set the new file name
|
|
245
|
+
let newFileName;
|
|
246
|
+
const storeName = storeNames[id];
|
|
247
|
+
|
|
248
|
+
managePackages(storeName);
|
|
249
|
+
|
|
250
|
+
if (storeName === "SamsungStore") {
|
|
251
|
+
// For SamsungStore, rename to versionCode value only
|
|
252
|
+
newFileName = `${finalVersionCode}.aab`;
|
|
253
|
+
} else {
|
|
254
|
+
// For other stores, use the standard naming format
|
|
255
|
+
newFileName = `app-release-signed-${storeName}-b${finalVersionCode}-v${finalVersionName}.aab`;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const checkFullPath = path.join("AAB", newFileName); // Update to point to the new AAB directory
|
|
259
|
+
|
|
260
|
+
// Modify minSdkVersion in variables.gradle for SamsungStore
|
|
261
|
+
const variablesGradleFilePath = path.join("android", "variables.gradle");
|
|
262
|
+
let variablesGradleContent = fs.readFileSync(variablesGradleFilePath, 'utf8');
|
|
263
|
+
|
|
264
|
+
// Extract the current minSdkVersion
|
|
265
|
+
const minSdkVersionMatch = variablesGradleContent.match(/minSdkVersion\s*=\s*(\d+)/);
|
|
266
|
+
const currentMinSdkVersion = minSdkVersionMatch ? parseInt(minSdkVersionMatch[1], 10) : null;
|
|
267
|
+
|
|
268
|
+
// Store the original minSdkVersion (only on the first iteration)
|
|
269
|
+
if (!originalMinSdkVersion) {
|
|
270
|
+
originalMinSdkVersion = currentMinSdkVersion;
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
// Modify the minSdkVersion based on the store
|
|
274
|
+
if (storeName === "SamsungStore" || storeName === "PlayStore") {
|
|
275
|
+
if (currentMinSdkVersion !== 24) {
|
|
276
|
+
variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, 'minSdkVersion = 24');
|
|
277
|
+
console.log('minSdkVersion updated to 24 for SamsungStore & PlayStore');
|
|
278
|
+
fs.writeFileSync(variablesGradleFilePath, variablesGradleContent);
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
// For PlayStore and AmazonStore, ensure minSdkVersion is originalMinSdkVersion
|
|
282
|
+
if (currentMinSdkVersion !== originalMinSdkVersion) {
|
|
283
|
+
variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, `minSdkVersion = ${originalMinSdkVersion}`);
|
|
284
|
+
console.log(`minSdkVersion reverted to ${originalMinSdkVersion} for ${storeName}`);
|
|
285
|
+
fs.writeFileSync(variablesGradleFilePath, variablesGradleContent);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Run the Node.js script to modify plugin.xml
|
|
290
|
+
if (isAdmobFound) {
|
|
291
|
+
child_process.execSync('node modify-plugin-xml.js', { stdio: 'inherit' });
|
|
292
|
+
} else {
|
|
293
|
+
console.log("\x1b[33m%s\x1b[0m", "Seems to Pro Version [No ads found]");
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Run the Vite build
|
|
297
|
+
child_process.execSync(`npm run build:storeid${id}`, { stdio: 'inherit' });
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
// Copy the built files to the appropriate folder
|
|
302
|
+
const src = path.join("www", "*");
|
|
303
|
+
const dest = path.join("android", "app", "src", "main", "assets", "public");
|
|
304
|
+
|
|
305
|
+
// Use 'xcopy' command for Windows
|
|
306
|
+
child_process.execSync(`xcopy ${src} ${dest} /E /I /Y`, { stdio: 'inherit' });
|
|
307
|
+
|
|
308
|
+
// Build Android AAB file
|
|
309
|
+
//child_process.execSync('cd android && ./gradlew bundleRelease', { stdio: 'inherit' });
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
// Build Android AAB file with Capacitor
|
|
313
|
+
child_process.execSync('npx cap sync android', { stdio: 'inherit' });
|
|
314
|
+
child_process.execSync('npx cap build android --androidreleasetype=AAB', { stdio: 'inherit' });
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
// Rename the output AAB file
|
|
318
|
+
const oldFilePath = path.join(aabDirectory, "app-release-signed.aab");
|
|
319
|
+
if (fs.existsSync(oldFilePath)) {
|
|
320
|
+
fs.renameSync(oldFilePath, checkFullPath);
|
|
321
|
+
console.log(`Renamed output AAB file to: ${newFileName}`);
|
|
322
|
+
} else {
|
|
323
|
+
console.error("AAB file not found after build.");
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
} catch (error) {
|
|
327
|
+
console.error(`Error during build for Store ID ${id}:`, error);
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
rl.close(); // Close the readline interface after all operations
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
function managePackages(store) {
|
|
340
|
+
console.log(`IAP Configurations - PlayStore: ${playstore}, Samsung: ${samsung}, Amazon: ${amazon}`);
|
|
341
|
+
|
|
342
|
+
let install = "";
|
|
343
|
+
let uninstall = "";
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
let manifestContent = fs.readFileSync(androidManifestPath, 'utf-8');
|
|
348
|
+
|
|
349
|
+
const permissionsToRemove = [
|
|
350
|
+
'com.android.vending.BILLING',
|
|
351
|
+
'com.samsung.android.iap.permission.BILLING'
|
|
352
|
+
];
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
permissionsToRemove.forEach(permission => {
|
|
356
|
+
const permissionRegex = new RegExp(`^\\s*<uses-permission\\s+android:name="${permission}"\\s*/?>\\s*[\r\n]?`, 'm');
|
|
357
|
+
if (permissionRegex.test(manifestContent)) {
|
|
358
|
+
manifestContent = manifestContent.replace(permissionRegex, '');
|
|
359
|
+
console.log(`Removed <uses-permission android:name="${permission}" /> from AndroidManifest.xml`);
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
// Write the updated content back to the file
|
|
364
|
+
fs.writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
if ((playstore && store === "PlayStore") || (amazon && store === "AmazonStore")) {
|
|
369
|
+
install = '@revenuecat/purchases-capacitor';
|
|
370
|
+
uninstall = 'cordova-plugin-samsungiap';
|
|
371
|
+
|
|
372
|
+
// Update AndroidManifest.xml for PlayStore
|
|
373
|
+
if(playstore)
|
|
374
|
+
updateAndroidManifest(store,
|
|
375
|
+
'<uses-permission android:name="com.android.vending.BILLING" />');
|
|
376
|
+
|
|
377
|
+
} else if (samsung && store === "SamsungStore") {
|
|
378
|
+
install = 'cordova-plugin-samsungiap';
|
|
379
|
+
uninstall = '@revenuecat/purchases-capacitor';
|
|
380
|
+
|
|
381
|
+
// Update AndroidManifest.xml for SamsungStore
|
|
382
|
+
updateAndroidManifest(store,
|
|
383
|
+
'<uses-permission android:name="com.samsung.android.iap.permission.BILLING" />');
|
|
384
|
+
|
|
385
|
+
} else {
|
|
386
|
+
console.log("No valid store specified or no configurations found. Both plugins will be uninstalled.");
|
|
387
|
+
try {
|
|
388
|
+
child_process.execSync(`npm uninstall cordova-plugin-samsungiap`, { stdio: 'inherit' });
|
|
389
|
+
child_process.execSync(`npm uninstall @revenuecat/purchases-capacitor`, { stdio: 'inherit' });
|
|
390
|
+
console.log(`Both plugins uninstalled successfully.`);
|
|
391
|
+
} catch (err) {
|
|
392
|
+
console.error("Error uninstalling plugins:", err);
|
|
393
|
+
}
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
console.log(`Installing ${install} and uninstalling ${uninstall} for ${store}...`);
|
|
398
|
+
try {
|
|
399
|
+
if (install) {
|
|
400
|
+
child_process.execSync(`npm install ${install}`, { stdio: 'inherit' });
|
|
401
|
+
}
|
|
402
|
+
if (uninstall) {
|
|
403
|
+
child_process.execSync(`npm uninstall ${uninstall}`, { stdio: 'inherit' });
|
|
404
|
+
}
|
|
405
|
+
console.log(`${install} installed and ${uninstall} uninstalled successfully.`);
|
|
406
|
+
} catch (err) {
|
|
407
|
+
console.error(`Error managing packages for ${store}:`, err);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
function updateAndroidManifest(store, addPermission) {
|
|
414
|
+
try {
|
|
415
|
+
if (!fs.existsSync(androidManifestPath)) {
|
|
416
|
+
console.error("AndroidManifest.xml file not found!");
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Read the content of the AndroidManifest.xml
|
|
421
|
+
let manifestContent = fs.readFileSync(androidManifestPath, 'utf-8');
|
|
422
|
+
|
|
423
|
+
// Normalize line endings to `\n` for consistent processing
|
|
424
|
+
manifestContent = manifestContent.replace(/\r\n/g, '\n');
|
|
425
|
+
|
|
426
|
+
// Check if the permission is already present
|
|
427
|
+
if (manifestContent.includes(addPermission.trim())) {
|
|
428
|
+
console.log(`${addPermission} is already in the AndroidManifest.xml. Skipping addition.`);
|
|
429
|
+
return; // Skip if the permission is already present
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Insert the permission before the closing </manifest> tag
|
|
433
|
+
const closingTag = '</manifest>';
|
|
434
|
+
const formattedPermission = ` ${addPermission.trim()}\n`;
|
|
435
|
+
if (manifestContent.includes(closingTag)) {
|
|
436
|
+
manifestContent = manifestContent.replace(
|
|
437
|
+
closingTag,
|
|
438
|
+
`${formattedPermission}${closingTag}`
|
|
439
|
+
);
|
|
440
|
+
console.log(`Added ${addPermission} before </manifest> tag.`);
|
|
441
|
+
} else {
|
|
442
|
+
console.warn(`</manifest> tag not found. Adding ${addPermission} at the end of the file.`);
|
|
443
|
+
manifestContent += `\n${formattedPermission}`;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Normalize line endings back to `\r\n` and write the updated content
|
|
447
|
+
manifestContent = manifestContent.replace(/\n/g, '\r\n');
|
|
448
|
+
fs.writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
449
|
+
console.log(`AndroidManifest.xml updated successfully for ${store}`);
|
|
450
|
+
} catch (err) {
|
|
451
|
+
console.error(`Error updating AndroidManifest.xml for ${store}:`, err);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
/* function updateAndroidManifest1(store, addPermission) {
|
|
458
|
+
try {
|
|
459
|
+
if (!fs.existsSync(androidManifestPath)) {
|
|
460
|
+
console.error("AndroidManifest.xml file not found!");
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
let manifestContent = fs.readFileSync(androidManifestPath, 'utf-8');
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
// Add the required permission if not already present
|
|
469
|
+
if (!manifestContent.includes(addPermission)) {
|
|
470
|
+
const manifestLines = manifestContent.split('\n');
|
|
471
|
+
const insertIndex = manifestLines.findIndex(line => line.trim().startsWith('<application'));
|
|
472
|
+
if (insertIndex > -1) {
|
|
473
|
+
manifestLines.splice(insertIndex, 0, ` ${addPermission}`);
|
|
474
|
+
manifestContent = manifestLines.join('\n');
|
|
475
|
+
console.log(`Added ${addPermission} to AndroidManifest.xml`);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Write the updated content back to the file
|
|
480
|
+
fs.writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
481
|
+
console.log(`AndroidManifest.xml updated successfully for ${store}`);
|
|
482
|
+
} catch (err) {
|
|
483
|
+
console.error(`Error updating AndroidManifest.xml for ${store}:`, err);
|
|
484
|
+
}
|
|
485
|
+
} */
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const androidManifestPath = path.join("android", "app", "src", "main", "AndroidManifest.xml");
|
|
7
|
+
|
|
8
|
+
// Find the vite config file
|
|
9
|
+
const possibleConfigFiles = ['vite.config.mjs', 'vite.config.js'];
|
|
10
|
+
let viteConfigPath;
|
|
11
|
+
|
|
12
|
+
for (const configFile of possibleConfigFiles) {
|
|
13
|
+
const fullPath = path.resolve(configFile);
|
|
14
|
+
if (fs.existsSync(fullPath)) {
|
|
15
|
+
viteConfigPath = fullPath;
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!viteConfigPath) {
|
|
21
|
+
console.error('Error: No vite.config.mjs or vite.config.js file found.');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
// Read vite config file
|
|
27
|
+
const viteConfigContent = fs.readFileSync(viteConfigPath, 'utf-8');
|
|
28
|
+
|
|
29
|
+
// Extract @common alias path
|
|
30
|
+
const aliasPattern = /'@common':\s*path\.resolve\(__dirname,\s*'(.+?)'\)/;
|
|
31
|
+
const match = viteConfigContent.match(aliasPattern);
|
|
32
|
+
|
|
33
|
+
if (!match) {
|
|
34
|
+
console.error(`Error: @common alias not found in ${viteConfigPath}`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const commonFilePath = match[1];
|
|
39
|
+
const resolvedCommonPath = path.resolve(__dirname, commonFilePath);
|
|
40
|
+
|
|
41
|
+
// Read the common file content
|
|
42
|
+
if (!fs.existsSync(resolvedCommonPath)) {
|
|
43
|
+
console.error(`Error: Resolved common file does not exist: ${resolvedCommonPath}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const commonFileContent = fs.readFileSync(resolvedCommonPath, 'utf-8');
|
|
48
|
+
|
|
49
|
+
// Extract _storeid value
|
|
50
|
+
const storeIdPattern = /export\s+let\s+_storeid\s*=\s*(?:import\.meta\.env\.VITE_STORE_ID\|\|)?(\d+)/;
|
|
51
|
+
const storeMatch = commonFileContent.match(storeIdPattern);
|
|
52
|
+
|
|
53
|
+
if (!storeMatch) {
|
|
54
|
+
console.error(`Error: _storeid not found in ${resolvedCommonPath}`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const _storeid = parseInt(storeMatch[1], 10);
|
|
59
|
+
|
|
60
|
+
// Determine the store name based on _storeid
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
let storeName = "";
|
|
65
|
+
if (_storeid === 1) {
|
|
66
|
+
storeName = "PlayStore";
|
|
67
|
+
} else if (_storeid === 2) {
|
|
68
|
+
storeName = "SamsungStore";
|
|
69
|
+
} else if (_storeid === 7) {
|
|
70
|
+
storeName = "AmazonStore";
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
console.error(`Error: Unsupported _storeid value: ${_storeid}`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Call managePackages with the determined store name
|
|
78
|
+
managePackages(storeName);
|
|
79
|
+
|
|
80
|
+
console.log(commonFilePath, `Success - _storeid found: ${_storeid}, Store: ${storeName}`);
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.error('Error:', error);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function managePackages(store) {
|
|
87
|
+
console.log(`Managing packages for store: ${store}`);
|
|
88
|
+
|
|
89
|
+
let install = "";
|
|
90
|
+
let uninstall = "";
|
|
91
|
+
|
|
92
|
+
//let androidManifestPath = "path/to/AndroidManifest.xml"; // Update this path
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
let manifestContent = fs.readFileSync(androidManifestPath, 'utf-8');
|
|
96
|
+
|
|
97
|
+
const permissionsToRemove = [
|
|
98
|
+
'com.android.vending.BILLING',
|
|
99
|
+
'com.samsung.android.iap.permission.BILLING'
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
permissionsToRemove.forEach(permission => {
|
|
103
|
+
const permissionRegex = new RegExp(`^\\s*<uses-permission\\s+android:name="${permission}"\\s*/?>\\s*[\r\n]?`, 'm');
|
|
104
|
+
if (permissionRegex.test(manifestContent)) {
|
|
105
|
+
manifestContent = manifestContent.replace(permissionRegex, '');
|
|
106
|
+
console.log(`Removed <uses-permission android:name="${permission}" /> from AndroidManifest.xml`);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Write the updated content back to the file
|
|
111
|
+
fs.writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
112
|
+
|
|
113
|
+
if (store === "PlayStore") {
|
|
114
|
+
install = '@revenuecat/purchases-capacitor';
|
|
115
|
+
uninstall = 'cordova-plugin-samsungiap';
|
|
116
|
+
} else if (store === "AmazonStore") {
|
|
117
|
+
install = '@revenuecat/purchases-capacitor';
|
|
118
|
+
uninstall = 'cordova-plugin-samsungiap';
|
|
119
|
+
} else if (store === "SamsungStore") {
|
|
120
|
+
install = 'cordova-plugin-samsungiap';
|
|
121
|
+
uninstall = '@revenuecat/purchases-capacitor';
|
|
122
|
+
} else {
|
|
123
|
+
console.log("No valid store specified. Uninstalling both plugins.");
|
|
124
|
+
try {
|
|
125
|
+
require('child_process').execSync(`npm uninstall cordova-plugin-samsungiap`, { stdio: 'inherit' });
|
|
126
|
+
require('child_process').execSync(`npm uninstall @revenuecat/purchases-capacitor`, { stdio: 'inherit' });
|
|
127
|
+
console.log("Both plugins uninstalled successfully.");
|
|
128
|
+
} catch (err) {
|
|
129
|
+
console.error("Error uninstalling plugins:", err);
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
console.log(`Installing ${install} and uninstalling ${uninstall} for ${store}...`);
|
|
135
|
+
try {
|
|
136
|
+
if (install) {
|
|
137
|
+
require('child_process').execSync(`npm install ${install}`, { stdio: 'inherit' });
|
|
138
|
+
}
|
|
139
|
+
if (uninstall) {
|
|
140
|
+
require('child_process').execSync(`npm uninstall ${uninstall}`, { stdio: 'inherit' });
|
|
141
|
+
}
|
|
142
|
+
console.log(`${install} installed and ${uninstall} uninstalled successfully.`);
|
|
143
|
+
} catch (err) {
|
|
144
|
+
console.error(`Error managing packages for ${store}:`, err);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
// Path to the plugin.xml file
|
|
5
|
+
const pluginXmlPath = path.join('node_modules', 'emi-indo-cordova-plugin-admob', 'plugin.xml');
|
|
6
|
+
|
|
7
|
+
// Get the store ID from the environment variable
|
|
8
|
+
const storeId = process.env.VITE_STORE_ID || '1';
|
|
9
|
+
|
|
10
|
+
// Determine the framework to use based on storeId
|
|
11
|
+
const framework = storeId === '7'
|
|
12
|
+
? '<framework src="com.google.android.gms:play-services-ads:$PLAY_SERVICES_VERSION" />'
|
|
13
|
+
: '<framework src="com.google.android.gms:play-services-ads-lite:$PLAY_SERVICES_VERSION" />';
|
|
14
|
+
|
|
15
|
+
// Read and modify the plugin.xml file
|
|
16
|
+
fs.readFile(pluginXmlPath, 'utf8', (err, data) => {
|
|
17
|
+
if (err) {
|
|
18
|
+
console.error('Error reading plugin.xml:', err);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Replace the existing framework line with the selected one
|
|
23
|
+
const modifiedData = data.replace(
|
|
24
|
+
/<framework src="com.google.android.gms:play-services-ads.*" \/>\n/,
|
|
25
|
+
`${framework}\n`
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// Write the modified content back to plugin.xml
|
|
29
|
+
fs.writeFile(pluginXmlPath, modifiedData, 'utf8', (err) => {
|
|
30
|
+
if (err) {
|
|
31
|
+
console.error('Error writing plugin.xml:', err);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
console.log('plugin.xml updated successfully.');
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const readline = require('readline');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
// Define the root directory of the project (adjust if needed)
|
|
6
|
+
const projectRoot = path.join('android/app/src/main');
|
|
7
|
+
|
|
8
|
+
// Animation options
|
|
9
|
+
const animations = [
|
|
10
|
+
{ id: 1, name: 'Ripple Effect', code: `.scaleX(1.2f).scaleY(1.2f).alpha(0.3f)` }, //Okay super
|
|
11
|
+
{ id: 2, name: 'Pop Out', code: `.scaleX(1.2f).scaleY(1.2f).alpha(0f)` }, //Okay super
|
|
12
|
+
{ id: 3, name: 'Super Zoom', code: `.scaleX(1.5f).scaleY(1.5f).alpha(1f)` }, //Okay super
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
{ id: 4, name: 'Flip and Fade', code: `.scaleX(0f).scaleY(0f).rotation(180f).alpha(0f)` }, //Okay
|
|
16
|
+
{ id: 5, name: 'Wipe Away', code: `.translationX(splashScreenView.getWidth()).alpha(0f)` }, //Okay
|
|
17
|
+
{ id: 6, name: 'Bounce in Spiral', code: `.scaleX(0.5f).scaleY(0.5f).alpha(0.5f).rotation(360f)` }, //Okay
|
|
18
|
+
{ id: 7, name: 'Fade and Slide', code: `.alpha(0f).translationY(splashScreenView.getHeight())` }, //Okay
|
|
19
|
+
{ id: 8, name: 'Zoom Out with Bounce', code: `.scaleX(0f).scaleY(0f).alpha(0f).translationY(splashScreenView.getHeight())` }, //Okay
|
|
20
|
+
{ id: 9, name: 'Twist', code: `.rotation(720f).alpha(0f)` }, //Okay
|
|
21
|
+
{ id: 10, name: 'Rotate Back', code: `.rotation(-360f).alpha(1f)` }, //Okay
|
|
22
|
+
{ id: 11, name: 'Stretch In', code: `.scaleX(1.5f).scaleY(1.5f).alpha(1f)` }, //Okay
|
|
23
|
+
{ id: 12, name: 'Fade and Scale', code: `.alpha(0f).scaleX(0f).scaleY(0f)` }, //Okay
|
|
24
|
+
{ id: 13, name: 'Slide Left and Fade', code: `.translationX(-splashScreenView.getWidth()).alpha(0f)` }, //Okay
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
{ id: 14, name: 'Fade Out', code: `.alpha(0f)` },
|
|
28
|
+
{ id: 15, name: 'Slide Down', code: `.translationY(splashScreenView.getHeight())` },
|
|
29
|
+
{ id: 16, name: 'Zoom Out', code: `.scaleX(0f).scaleY(0f).alpha(0f)` },
|
|
30
|
+
{ id: 17, name: 'Rotate Out', code: `.rotation(360f).alpha(0f)` },
|
|
31
|
+
{ id: 18, name: 'Slide Up', code: `.translationY(-splashScreenView.getHeight()).alpha(0f)` },
|
|
32
|
+
{ id: 19, name: 'Bounce Effect', code: `.translationY(splashScreenView.getHeight())` },
|
|
33
|
+
{ id: 20, name: 'Flip Out', code: `.scaleX(0f).alpha(0f)` },
|
|
34
|
+
{ id: 21, name: 'Diagonal Slide and Fade Out', code: `.translationX(splashScreenView.getWidth()).translationY(splashScreenView.getHeight()).alpha(0f)` },
|
|
35
|
+
{ id: 22, name: 'Scale Down with Bounce', code: `.scaleX(0f).scaleY(0f)` },
|
|
36
|
+
{ id: 23, name: 'Slide Left', code: `.translationX(-splashScreenView.getWidth()).alpha(0f)` },
|
|
37
|
+
{ id: 24, name: 'Slide Right', code: `.translationX(splashScreenView.getWidth()).alpha(0f)` },
|
|
38
|
+
{ id: 25, name: 'Scale Up', code: `.scaleX(1f).scaleY(1f).alpha(1f)` },
|
|
39
|
+
{ id: 26, name: 'Rotate In', code: `.rotation(180f).alpha(1f)` },
|
|
40
|
+
{ id: 27, name: 'Bounce Up', code: `.translationY(-100f).setInterpolator(new BounceInterpolator())` },
|
|
41
|
+
{ id: 28, name: 'Flip Horizontal', code: `.scaleX(-1f).alpha(1f)` },
|
|
42
|
+
{ id: 29, name: 'Zoom In', code: `.scaleX(1f).scaleY(1f).alpha(1f)` },
|
|
43
|
+
{ id: 30, name: 'Wobble', code: `.translationX(10f).translationX(-10f).translationX(10f)` },
|
|
44
|
+
{ id: 31, name: 'Vertical Shake', code: `.translationY(10f).translationY(-10f).translationY(10f)` },
|
|
45
|
+
{ id: 32, name: 'Bounce Down', code: `.translationY(100f).setInterpolator(new BounceInterpolator())` },
|
|
46
|
+
{ id: 33, name: 'Swing', code: `.rotation(15f).translationX(-10f).rotation(-15f).translationX(10f)` },
|
|
47
|
+
{ id: 34, name: 'Elastic Bounce', code: `.translationX(30f).translationX(-30f).translationX(15f).translationX(-15f)` },
|
|
48
|
+
{ id: 35, name: 'Pulse', code: `.scaleX(1.1f).scaleY(1.1f).alpha(1f).setRepeatMode(ValueAnimator.REVERSE).setRepeatCount(ValueAnimator.INFINITE)` },
|
|
49
|
+
{ id: 36, name: 'Skew', code: `.setRotationX(30f).setRotationY(30f).alpha(0.5f)` },
|
|
50
|
+
{ id: 37, name: 'Vibrate', code: `.translationX(5f).translationX(-5f).translationX(5f).translationX(-5f)` },
|
|
51
|
+
{ id: 38, name: 'Speed Out', code: `.alpha(0f).setDuration(300)` },
|
|
52
|
+
{ id: 39, name: 'Wave', code: `.translationX(20f).translationX(-20f).translationX(20f).translationX(-20f)` },
|
|
53
|
+
{ id: 40, name: 'Swing Bounce', code: `.rotation(15f).translationX(10f).translationX(-10f)` },
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
// Function to find the package name from capacitor.config.json
|
|
58
|
+
function findPackageName() {
|
|
59
|
+
const configPath = path.join('capacitor.config.json');
|
|
60
|
+
if (!fs.existsSync(configPath)) {
|
|
61
|
+
console.error('capacitor.config.json not found. Ensure this is a valid Capacitor project.');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const configContent = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
66
|
+
return configContent.appId;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Function to construct the MainActivity.java path
|
|
70
|
+
function constructMainActivityPath(packageName) {
|
|
71
|
+
const packagePath = packageName.replace(/\./g, '/'); // Convert package name to path
|
|
72
|
+
const mainActivityPath = path.join('android', 'app', 'src', 'main', 'java', packagePath, 'MainActivity.java');
|
|
73
|
+
|
|
74
|
+
console.log('MainActivity path:', mainActivityPath); // Output for debugging
|
|
75
|
+
return mainActivityPath;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Find package name and MainActivity.java path
|
|
79
|
+
const packageName = findPackageName();
|
|
80
|
+
if (!packageName) {
|
|
81
|
+
console.error('Failed to extract the package name from capacitor.config.json.');
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const mainActivityPath = constructMainActivityPath(packageName);
|
|
86
|
+
|
|
87
|
+
// Display animation options
|
|
88
|
+
/* const rl = readline.createInterface({
|
|
89
|
+
input: process.stdin,
|
|
90
|
+
output: process.stdout,
|
|
91
|
+
}); */
|
|
92
|
+
|
|
93
|
+
console.log('Select an animation type for the splash screen:');
|
|
94
|
+
animations.forEach((animation) => {
|
|
95
|
+
console.log(`${animation.id}. ${animation.name}`);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Prompt user for animation selection
|
|
99
|
+
//rl.question('Enter the number of the animation type: ', (answer) => {
|
|
100
|
+
|
|
101
|
+
const answer=1;
|
|
102
|
+
|
|
103
|
+
const selectedAnimation = animations.find((anim) => anim.id === parseInt(answer, 10));
|
|
104
|
+
|
|
105
|
+
if (!selectedAnimation) {
|
|
106
|
+
console.log('Invalid selection. Please run the script again.');
|
|
107
|
+
//rl.close();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
console.log(`Selected: ${selectedAnimation.name}`);
|
|
112
|
+
|
|
113
|
+
// Read the MainActivity.java file
|
|
114
|
+
fs.readFile(mainActivityPath, 'utf8', (err, data) => {
|
|
115
|
+
if (err) {
|
|
116
|
+
console.error(`Error reading MainActivity.java: ${err.message}`);
|
|
117
|
+
//rl.close();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// New logic for removing existing code and adding new splash screen animation code
|
|
122
|
+
const newMainActivityCode =
|
|
123
|
+
`package ${findPackageName()};
|
|
124
|
+
|
|
125
|
+
import android.os.Build;
|
|
126
|
+
import android.os.Bundle;
|
|
127
|
+
import com.getcapacitor.BridgeActivity;
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
public class MainActivity extends BridgeActivity {
|
|
131
|
+
@Override
|
|
132
|
+
protected void onCreate(Bundle savedInstanceState) {
|
|
133
|
+
super.onCreate(savedInstanceState);
|
|
134
|
+
|
|
135
|
+
// Handle custom splash screen exit animation
|
|
136
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
137
|
+
getSplashScreen().setOnExitAnimationListener(splashScreenView -> {
|
|
138
|
+
// Add your custom animation here (e.g., fade out)
|
|
139
|
+
splashScreenView.setAlpha(1f);
|
|
140
|
+
splashScreenView.animate()
|
|
141
|
+
${selectedAnimation.code} // Apply selected animation
|
|
142
|
+
.setDuration(1000) // Animation duration (1000ms)
|
|
143
|
+
.withEndAction(splashScreenView::remove) // Remove splash screen
|
|
144
|
+
.start();
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
`;
|
|
150
|
+
|
|
151
|
+
// Write the new MainActivity.java content
|
|
152
|
+
writeMainActivity(newMainActivityCode);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
//rl.close();
|
|
156
|
+
//});
|
|
157
|
+
|
|
158
|
+
// Write updated data to MainActivity.java
|
|
159
|
+
function writeMainActivity(updatedData) {
|
|
160
|
+
fs.writeFile(mainActivityPath, updatedData, 'utf8', (err) => {
|
|
161
|
+
if (err) {
|
|
162
|
+
console.error(`Error writing to MainActivity.java: ${err.message}`);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
console.log('MainActivity.java updated successfully!');
|
|
166
|
+
});
|
|
167
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<resources>
|
|
3
|
+
<color name="splashscreen_background">#FFFFFF</color>
|
|
4
|
+
|
|
5
|
+
<style name="Theme.Codeplay.SplashScreen" parent="Theme.SplashScreen.IconBackground">
|
|
6
|
+
<item name="windowSplashScreenBackground">@color/splashscreen_background</item>
|
|
7
|
+
<item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon</item>
|
|
8
|
+
<item name="windowSplashScreenAnimationDuration">10000</item>
|
|
9
|
+
<item name="postSplashScreenTheme">@style/Theme.AppCompat.NoActionBar</item>
|
|
10
|
+
</style>
|
|
11
|
+
</resources>
|
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "codeplay-common",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Common build scripts and files",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"postinstall": "node scripts/sync-files.js"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/merbin2012/codeplay-common.git"
|
|
12
|
+
},
|
|
13
|
+
"author": "Codeplay Technologies",
|
|
14
|
+
"license": "MIT"
|
|
15
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
const projectRoot = process.cwd(); // Project root where this package is installed
|
|
5
|
+
const commonBuildPath = path.join(__dirname, "../files"); // Path to "Common Build File" folder
|
|
6
|
+
const packageJsonPath = path.join(projectRoot, "package.json");
|
|
7
|
+
|
|
8
|
+
// Ensure package.json exists
|
|
9
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
10
|
+
console.error("❌ Error: package.json not found in project.");
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Function to get the latest versioned file dynamically
|
|
15
|
+
function getLatestFile(prefix) {
|
|
16
|
+
const files = fs.readdirSync(commonBuildPath);
|
|
17
|
+
const matchingFiles = files.filter(file => file.startsWith(prefix));
|
|
18
|
+
|
|
19
|
+
if (matchingFiles.length === 0) {
|
|
20
|
+
console.warn(`⚠️ Warning: No file found for ${prefix}`);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Sort files by version and pick the latest one
|
|
25
|
+
matchingFiles.sort((a, b) => b.localeCompare(a, undefined, { numeric: true }));
|
|
26
|
+
return matchingFiles[0];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Copy all files from "files" folder to the project root
|
|
30
|
+
fs.readdirSync(commonBuildPath).forEach(file => {
|
|
31
|
+
fs.copyFileSync(path.join(commonBuildPath, file), path.join(projectRoot, file));
|
|
32
|
+
console.log(`✅ Copied: ${file}`);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Get the latest versions
|
|
36
|
+
const latestSplashScreen = getLatestFile("add-splash-screen-");
|
|
37
|
+
const latestSplashAnimation = getLatestFile("setSplashAnimation-");
|
|
38
|
+
const latestCodeplayBuild = getLatestFile("codeplayBeforeBuild-");
|
|
39
|
+
|
|
40
|
+
// Read and update package.json
|
|
41
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
42
|
+
|
|
43
|
+
// Update only the versioned script names in package.json
|
|
44
|
+
if (latestSplashScreen) {
|
|
45
|
+
packageJson.scripts["capacitor:sync:after"] = packageJson.scripts["capacitor:sync:after"].replace(
|
|
46
|
+
/add-splash-screen-\d+\.\d+\.js/,
|
|
47
|
+
latestSplashScreen
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (latestSplashAnimation) {
|
|
52
|
+
packageJson.scripts["capacitor:sync:after"] = packageJson.scripts["capacitor:sync:after"].replace(
|
|
53
|
+
/setSplashAnimation-\d+\.\d+\.js/,
|
|
54
|
+
latestSplashAnimation
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (latestCodeplayBuild) {
|
|
59
|
+
packageJson.scripts["build"] = packageJson.scripts["build"].replace(
|
|
60
|
+
/codeplayBeforeBuild-\d+\.\d+\.js/,
|
|
61
|
+
latestCodeplayBuild
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Write updated package.json
|
|
66
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf8");
|
|
67
|
+
console.log("✅ package.json updated successfully!");
|