codeplay-common 4.7.1 → 4.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +2 -2
- package/LICENSE +21 -21
- package/README.md +120 -120
- package/files/buildCodeplay/codeplayBeforeBuild-6.3.js +58 -0
- package/files/buildCodeplay/release-sync.config.json +4 -4
- package/files/finalrelease +49 -49
- package/files/generate-ai-promo-video.js +23 -23
- package/files/iap-install-2.js +145 -145
- package/files/ionic.config.json +6 -6
- package/files/scripts/frame-samples.js +117 -0
- package/files/scripts/setup-baseline-profile.js +262 -262
- package/files/take-screen-image.js +204 -25
- package/files/take-screen-video.js +644 -644
- package/package.json +15 -15
- package/scripts/sync-files.js +103 -103
- package/scripts/uninstall.js +109 -109
package/files/iap-install-2.js
CHANGED
|
@@ -1,145 +1,145 @@
|
|
|
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\s*\|\|\s*(\d+)\s*;/;
|
|
51
|
-
|
|
52
|
-
const storeMatch = commonFileContent.match(storeIdPattern);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (!storeMatch) {
|
|
56
|
-
console.error(`Error: _storeid not found in ${resolvedCommonPath}`);
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const _storeid = parseInt(storeMatch[1], 10);
|
|
61
|
-
|
|
62
|
-
// Determine the store name based on _storeid
|
|
63
|
-
let storeName = "";
|
|
64
|
-
if (_storeid === 1) {
|
|
65
|
-
storeName = "PlayStore";
|
|
66
|
-
} else if (_storeid === 2) {
|
|
67
|
-
storeName = "SamsungStore";
|
|
68
|
-
} else if (_storeid === 7) {
|
|
69
|
-
storeName = "AmazonStore";
|
|
70
|
-
} else {
|
|
71
|
-
console.error(`Error: Unsupported _storeid value: ${_storeid}`);
|
|
72
|
-
process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// Call managePackages with the determined store name
|
|
77
|
-
managePackages(storeName);
|
|
78
|
-
|
|
79
|
-
console.log(commonFilePath, `Success - _storeid found: ${_storeid}, Store: ${storeName}`);
|
|
80
|
-
} catch (error) {
|
|
81
|
-
console.error('Error:', error);
|
|
82
|
-
process.exit(1);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function managePackages(store) {
|
|
86
|
-
console.log(`Managing packages for store: ${store}`);
|
|
87
|
-
|
|
88
|
-
let install = "";
|
|
89
|
-
let uninstall = "";
|
|
90
|
-
|
|
91
|
-
//let androidManifestPath = "path/to/AndroidManifest.xml"; // Update this path
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
let manifestContent = fs.readFileSync(androidManifestPath, 'utf-8');
|
|
95
|
-
|
|
96
|
-
const permissionsToRemove = [
|
|
97
|
-
'com.android.vending.BILLING',
|
|
98
|
-
'com.samsung.android.iap.permission.BILLING'
|
|
99
|
-
];
|
|
100
|
-
|
|
101
|
-
permissionsToRemove.forEach(permission => {
|
|
102
|
-
const permissionRegex = new RegExp(`^\\s*<uses-permission\\s+android:name="${permission}"\\s*/?>\\s*[\r\n]?`, 'm');
|
|
103
|
-
if (permissionRegex.test(manifestContent)) {
|
|
104
|
-
manifestContent = manifestContent.replace(permissionRegex, '');
|
|
105
|
-
console.log(`Removed <uses-permission android:name="${permission}" /> from AndroidManifest.xml`);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
// Write the updated content back to the file
|
|
110
|
-
fs.writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
111
|
-
|
|
112
|
-
if (store === "PlayStore") {
|
|
113
|
-
install = '@revenuecat/purchases-capacitor';
|
|
114
|
-
uninstall = 'cordova-plugin-samsungiap';
|
|
115
|
-
} else if (store === "AmazonStore") {
|
|
116
|
-
install = '@revenuecat/purchases-capacitor';
|
|
117
|
-
uninstall = 'cordova-plugin-samsungiap';
|
|
118
|
-
} else if (store === "SamsungStore") {
|
|
119
|
-
install = 'cordova-plugin-samsungiap';
|
|
120
|
-
uninstall = '@revenuecat/purchases-capacitor';
|
|
121
|
-
} else {
|
|
122
|
-
console.log("No valid store specified. Uninstalling both plugins.");
|
|
123
|
-
try {
|
|
124
|
-
require('child_process').execSync(`npm uninstall cordova-plugin-samsungiap`, { stdio: 'inherit' });
|
|
125
|
-
require('child_process').execSync(`npm uninstall @revenuecat/purchases-capacitor`, { stdio: 'inherit' });
|
|
126
|
-
console.log("Both plugins uninstalled successfully.");
|
|
127
|
-
} catch (err) {
|
|
128
|
-
console.error("Error uninstalling plugins:", err);
|
|
129
|
-
}
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
console.log(`Installing ${install} and uninstalling ${uninstall} for ${store}...`);
|
|
134
|
-
try {
|
|
135
|
-
if (install) {
|
|
136
|
-
require('child_process').execSync(`npm install ${install}`, { stdio: 'inherit' });
|
|
137
|
-
}
|
|
138
|
-
if (uninstall) {
|
|
139
|
-
require('child_process').execSync(`npm uninstall ${uninstall}`, { stdio: 'inherit' });
|
|
140
|
-
}
|
|
141
|
-
console.log(`${install} installed and ${uninstall} uninstalled successfully.`);
|
|
142
|
-
} catch (err) {
|
|
143
|
-
console.error(`Error managing packages for ${store}:`, err);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
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\s*\|\|\s*(\d+)\s*;/;
|
|
51
|
+
|
|
52
|
+
const storeMatch = commonFileContent.match(storeIdPattern);
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
if (!storeMatch) {
|
|
56
|
+
console.error(`Error: _storeid not found in ${resolvedCommonPath}`);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const _storeid = parseInt(storeMatch[1], 10);
|
|
61
|
+
|
|
62
|
+
// Determine the store name based on _storeid
|
|
63
|
+
let storeName = "";
|
|
64
|
+
if (_storeid === 1) {
|
|
65
|
+
storeName = "PlayStore";
|
|
66
|
+
} else if (_storeid === 2) {
|
|
67
|
+
storeName = "SamsungStore";
|
|
68
|
+
} else if (_storeid === 7) {
|
|
69
|
+
storeName = "AmazonStore";
|
|
70
|
+
} else {
|
|
71
|
+
console.error(`Error: Unsupported _storeid value: ${_storeid}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
// Call managePackages with the determined store name
|
|
77
|
+
managePackages(storeName);
|
|
78
|
+
|
|
79
|
+
console.log(commonFilePath, `Success - _storeid found: ${_storeid}, Store: ${storeName}`);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error('Error:', error);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function managePackages(store) {
|
|
86
|
+
console.log(`Managing packages for store: ${store}`);
|
|
87
|
+
|
|
88
|
+
let install = "";
|
|
89
|
+
let uninstall = "";
|
|
90
|
+
|
|
91
|
+
//let androidManifestPath = "path/to/AndroidManifest.xml"; // Update this path
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
let manifestContent = fs.readFileSync(androidManifestPath, 'utf-8');
|
|
95
|
+
|
|
96
|
+
const permissionsToRemove = [
|
|
97
|
+
'com.android.vending.BILLING',
|
|
98
|
+
'com.samsung.android.iap.permission.BILLING'
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
permissionsToRemove.forEach(permission => {
|
|
102
|
+
const permissionRegex = new RegExp(`^\\s*<uses-permission\\s+android:name="${permission}"\\s*/?>\\s*[\r\n]?`, 'm');
|
|
103
|
+
if (permissionRegex.test(manifestContent)) {
|
|
104
|
+
manifestContent = manifestContent.replace(permissionRegex, '');
|
|
105
|
+
console.log(`Removed <uses-permission android:name="${permission}" /> from AndroidManifest.xml`);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Write the updated content back to the file
|
|
110
|
+
fs.writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
111
|
+
|
|
112
|
+
if (store === "PlayStore") {
|
|
113
|
+
install = '@revenuecat/purchases-capacitor';
|
|
114
|
+
uninstall = 'cordova-plugin-samsungiap';
|
|
115
|
+
} else if (store === "AmazonStore") {
|
|
116
|
+
install = '@revenuecat/purchases-capacitor';
|
|
117
|
+
uninstall = 'cordova-plugin-samsungiap';
|
|
118
|
+
} else if (store === "SamsungStore") {
|
|
119
|
+
install = 'cordova-plugin-samsungiap';
|
|
120
|
+
uninstall = '@revenuecat/purchases-capacitor';
|
|
121
|
+
} else {
|
|
122
|
+
console.log("No valid store specified. Uninstalling both plugins.");
|
|
123
|
+
try {
|
|
124
|
+
require('child_process').execSync(`npm uninstall cordova-plugin-samsungiap`, { stdio: 'inherit' });
|
|
125
|
+
require('child_process').execSync(`npm uninstall @revenuecat/purchases-capacitor`, { stdio: 'inherit' });
|
|
126
|
+
console.log("Both plugins uninstalled successfully.");
|
|
127
|
+
} catch (err) {
|
|
128
|
+
console.error("Error uninstalling plugins:", err);
|
|
129
|
+
}
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
console.log(`Installing ${install} and uninstalling ${uninstall} for ${store}...`);
|
|
134
|
+
try {
|
|
135
|
+
if (install) {
|
|
136
|
+
require('child_process').execSync(`npm install ${install}`, { stdio: 'inherit' });
|
|
137
|
+
}
|
|
138
|
+
if (uninstall) {
|
|
139
|
+
require('child_process').execSync(`npm uninstall ${uninstall}`, { stdio: 'inherit' });
|
|
140
|
+
}
|
|
141
|
+
console.log(`${install} installed and ${uninstall} uninstalled successfully.`);
|
|
142
|
+
} catch (err) {
|
|
143
|
+
console.error(`Error managing packages for ${store}:`, err);
|
|
144
|
+
}
|
|
145
|
+
}
|
package/files/ionic.config.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "merbin-test-app",
|
|
3
|
-
"integrations": {
|
|
4
|
-
"capacitor": {}
|
|
5
|
-
},
|
|
6
|
-
"type": "custom"
|
|
1
|
+
{
|
|
2
|
+
"name": "merbin-test-app",
|
|
3
|
+
"integrations": {
|
|
4
|
+
"capacitor": {}
|
|
5
|
+
},
|
|
6
|
+
"type": "custom"
|
|
7
7
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
const fs = require('node:fs');
|
|
2
|
+
const path = require('node:path');
|
|
3
|
+
const sharp = require('sharp');
|
|
4
|
+
|
|
5
|
+
const frameStyles = {
|
|
6
|
+
android: {
|
|
7
|
+
graphite: { label: 'A · Graphite Android', detail: 'Slim dark bezel', outer: '#151a24', edge: '#626d7f', inner: '#080b12', radius: 47 },
|
|
8
|
+
cobalt: { label: 'B · Cobalt Android', detail: 'Blue accent bezel', outer: '#1945bc', edge: '#8aa9ff', inner: '#07102f', radius: 43 },
|
|
9
|
+
},
|
|
10
|
+
ios: {
|
|
11
|
+
titanium: { label: 'C · Titanium iPhone', detail: 'Light metal edge', outer: '#c7ced6', edge: '#eef2f6', inner: '#222936', radius: 53 },
|
|
12
|
+
midnight: { label: 'D · Midnight iPhone', detail: 'Dark rounded edge', outer: '#202333', edge: '#586076', inner: '#080b12', radius: 53 },
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function getStatusBarSvg(platform, time) {
|
|
17
|
+
if (platform === 'ios') {
|
|
18
|
+
return `<rect x="12" y="22" width="316" height="40" fill="#f5f7fc"/>
|
|
19
|
+
<text x="29" y="47" font-family="Arial,sans-serif" font-size="14" font-weight="700" fill="#050505">${time}</text>
|
|
20
|
+
<circle cx="246" cy="40" r="2" fill="#c5c7cb"/><circle cx="254" cy="40" r="2" fill="#c5c7cb"/>
|
|
21
|
+
<circle cx="262" cy="40" r="2" fill="#c5c7cb"/><circle cx="270" cy="40" r="2" fill="#c5c7cb"/>
|
|
22
|
+
<path d="M275 35 Q284 27 293 35 M278 39 Q284 34 290 39 M282 43 Q284 41 286 43" fill="none" stroke="#050505" stroke-width="2.5" stroke-linecap="round"/>
|
|
23
|
+
<rect x="295" y="33" width="17" height="13" rx="3" fill="none" stroke="#a7aaae" stroke-width="1.5"/>
|
|
24
|
+
<rect x="297" y="35" width="13" height="9" rx="2" fill="#050505"/>
|
|
25
|
+
<rect x="313" y="37" width="2" height="5" rx="1" fill="#a7aaae"/>`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return `<rect x="12" y="22" width="316" height="40" fill="#9075ed"/>
|
|
29
|
+
<text x="29" y="47" font-family="Arial,sans-serif" font-size="14" fill="#ffffff">${time}</text>
|
|
30
|
+
<circle cx="86" cy="41" r="5" fill="none" stroke="#ffffff" stroke-width="1.2"/>
|
|
31
|
+
<circle cx="84" cy="40" r="0.8" fill="#ffffff"/><circle cx="88" cy="40" r="0.8" fill="#ffffff"/>
|
|
32
|
+
<g transform="translate(-15,0)">
|
|
33
|
+
<text x="200" y="36" font-family="Arial,sans-serif" font-size="7" font-weight="700" fill="#ffffff">0.26</text>
|
|
34
|
+
<text x="200" y="44" font-family="Arial,sans-serif" font-size="6" font-weight="700" fill="#ffffff">KB/s</text>
|
|
35
|
+
<path d="M222 43 L235 33 L235 43 Z M242 43 L254 33 L254 43 Z" fill="#ffffff"/>
|
|
36
|
+
<text x="257" y="39" font-family="Arial,sans-serif" font-size="7" font-weight="700" fill="#ffffff">Vo</text>
|
|
37
|
+
<text x="257" y="46" font-family="Arial,sans-serif" font-size="6" font-weight="700" fill="#ffffff">WiFi</text>
|
|
38
|
+
<path d="M274 35 Q283 27 292 35 M277 39 Q283 34 289 39 M281 43 Q283 41 285 43" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/>
|
|
39
|
+
<rect x="296" y="34" width="19" height="11" rx="2" fill="none" stroke="#ffffff" stroke-width="1.4"/>
|
|
40
|
+
<path d="M305 33 L301 40 L306 40 L304 46 L312 38 L307 38 L310 33 Z" fill="#ffffff"/>
|
|
41
|
+
<text x="317" y="43" font-family="Arial,sans-serif" font-size="7" fill="#ffffff">87%</text>
|
|
42
|
+
</g>`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function createFallbackScreenshot(platform) {
|
|
46
|
+
const width = platform === 'ios' ? 1320 : 1080;
|
|
47
|
+
const height = platform === 'ios' ? 2868 : 2400;
|
|
48
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
|
|
49
|
+
<rect width="100%" height="100%" fill="#f5f7fc"/>
|
|
50
|
+
<rect x="8%" y="26%" width="84%" height="20%" rx="60" fill="#d7ddff"/>
|
|
51
|
+
<text x="50%" y="37%" text-anchor="middle" font-family="Arial,sans-serif" font-size="62" font-weight="700" fill="#4446c6">Image Compressor</text>
|
|
52
|
+
<rect x="8%" y="62%" width="84%" height="8%" rx="55" fill="#5145e7"/>
|
|
53
|
+
<text x="50%" y="67%" text-anchor="middle" font-family="Arial,sans-serif" font-size="42" font-weight="700" fill="#ffffff">Select images</text>
|
|
54
|
+
</svg>`;
|
|
55
|
+
return sharp(Buffer.from(svg)).png().toBuffer();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function getSampleScreenshot(autoScreenshotDirectory, platform) {
|
|
59
|
+
const directory = path.join(autoScreenshotDirectory, 'Store-image-Screenshot', platform === 'ios' ? 'iPhone' : 'Android');
|
|
60
|
+
if (fs.existsSync(directory)) {
|
|
61
|
+
const screenshot = fs.readdirSync(directory).filter((name) => /\.png$/i.test(name)).sort()[0];
|
|
62
|
+
if (screenshot) return fs.readFileSync(path.join(directory, screenshot));
|
|
63
|
+
}
|
|
64
|
+
return createFallbackScreenshot(platform);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function createSampleCard(style, platform, screenshotUrl, index) {
|
|
68
|
+
const screenRadius = platform === 'ios' ? 40 : 34;
|
|
69
|
+
const sampleTime = platform === 'ios' ? (index ? '12:21' : '12:20') : (index ? '10:56' : '10:55');
|
|
70
|
+
const camera = platform === 'ios'
|
|
71
|
+
? '<rect x="130" y="27" width="80" height="24" rx="12" fill="#05070b"/>'
|
|
72
|
+
: '';
|
|
73
|
+
const navigation = platform === 'android'
|
|
74
|
+
? '<rect x="12" y="717" width="316" height="16" fill="#f4f7f8"/><rect x="107" y="725" width="126" height="3" rx="1.5" fill="#7a7b7c"/>'
|
|
75
|
+
: '';
|
|
76
|
+
|
|
77
|
+
return `<g transform="translate(${index * 510},0)">
|
|
78
|
+
<rect x="12" y="12" width="486" height="926" rx="25" fill="#ffffff" stroke="#dce2ee"/>
|
|
79
|
+
<text x="35" y="52" fill="#172137" font-family="Arial,sans-serif" font-size="24" font-weight="700">${style.label}</text>
|
|
80
|
+
<text x="35" y="80" fill="#6c7890" font-family="Arial,sans-serif" font-size="14">${style.detail} · ${platform === 'ios' ? 'iOS' : 'Android'} status bar</text>
|
|
81
|
+
<g transform="translate(85,115)">
|
|
82
|
+
<rect x="1" y="7" width="338" height="753" rx="47" fill="#0a1225" opacity="0.2"/>
|
|
83
|
+
<rect x="1" y="1" width="338" height="753" rx="${style.radius}" fill="${style.outer}" stroke="${style.edge}" stroke-width="2"/>
|
|
84
|
+
<rect x="7" y="7" width="326" height="741" rx="${style.radius - 5}" fill="${style.inner}"/>
|
|
85
|
+
<clipPath id="screen-${index}"><rect x="12" y="22" width="316" height="711" rx="${screenRadius}"/></clipPath>
|
|
86
|
+
<g clip-path="url(#screen-${index})">
|
|
87
|
+
<rect x="12" y="22" width="316" height="711" fill="#f5f7fc"/>
|
|
88
|
+
<image href="${screenshotUrl}" x="12" y="62" width="316" height="671" preserveAspectRatio="xMidYMin slice"/>
|
|
89
|
+
${getStatusBarSvg(platform, sampleTime)}
|
|
90
|
+
${navigation}
|
|
91
|
+
</g>
|
|
92
|
+
${camera}
|
|
93
|
+
<rect x="338" y="177" width="4" height="66" rx="2" fill="${style.edge}"/>
|
|
94
|
+
</g>
|
|
95
|
+
</g>`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function createFrameSamples(autoScreenshotDirectory) {
|
|
99
|
+
fs.mkdirSync(autoScreenshotDirectory, { recursive: true });
|
|
100
|
+
const paths = [];
|
|
101
|
+
|
|
102
|
+
for (const platform of ['android', 'ios']) {
|
|
103
|
+
const screenshot = await getSampleScreenshot(autoScreenshotDirectory, platform);
|
|
104
|
+
const screenshotUrl = `data:image/png;base64,${screenshot.toString('base64')}`;
|
|
105
|
+
const cards = Object.values(frameStyles[platform])
|
|
106
|
+
.map((style, index) => createSampleCard(style, platform, screenshotUrl, index))
|
|
107
|
+
.join('');
|
|
108
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="1020" height="950" viewBox="0 0 1020 950"><rect width="1020" height="950" fill="#eef2f9"/>${cards}</svg>`;
|
|
109
|
+
const output = path.join(autoScreenshotDirectory, `${platform}-frame-options.png`);
|
|
110
|
+
await sharp(Buffer.from(svg)).png().toFile(output);
|
|
111
|
+
paths.push(output);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return paths;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
module.exports = { frameStyles, createFrameSamples };
|