rock
Version:
Command-line interface for Rock - a React Native development toolkit
415 lines (380 loc) • 11.6 kB
JavaScript
// Template functions for ad-hoc iOS and Android distribution
// Shared CSS styles for both iOS and Android templates
const sharedStyles = `
:root {
/* Light mode variables */
--bg-primary: #ffffff;
--bg-secondary: #f5f5f7;
--text-primary: #1d1d1f;
--text-secondary: #86868b;
--accent-primary: #8232ff;
--accent-hover: rgba(130, 50, 255, 0.3);
--border-color: #e5e5e7;
--shadow-color: rgba(0, 0, 0, 0.1);
}
@media (prefers-color-scheme: dark) {
:root {
/* Dark mode variables */
--bg-primary: #1c1c1e;
--bg-secondary: #2c2c2e;
--text-primary: #ffffff;
--text-secondary: #8e8e93;
--accent-primary: #8232ff;
--accent-hover: rgba(130, 50, 255, 0.4);
--border-color: #38383a;
--shadow-color: rgba(0, 0, 0, 0.3);
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Oxygen, Ubuntu, Cantarell, sans-serif;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
font-size: 16px;
background-color: var(--bg-primary);
color: var(--text-primary);
transition: background-color 0.3s ease, color 0.3s ease;
}
.container {
text-align: center;
max-width: 500px;
width: 100%;
}
.app-icon {
width: 100px;
height: 100px;
margin: 0 auto 15px;
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
color: var(--text-primary);
background: var(--bg-secondary);
border-radius: 25px;
transition: background-color 0.3s ease;
}
h1 {
color: var(--text-primary);
font-size: 28px;
font-weight: 600;
margin-bottom: 15px;
overflow-wrap: break-word;
transition: color 0.3s ease;
}
.subtitle {
color: var(--text-secondary);
font-size: 16px;
line-height: 1.5;
margin-bottom: 30px;
transition: color 0.3s ease;
}
.version {
color: var(--text-primary);
font-size: 16px;
line-height: 1.5;
margin-bottom: 10px;
transition: color 0.3s ease;
}
.download-button {
background: var(--accent-primary);
color: white;
border: none;
padding: 16px 32px;
border-radius: 4px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
display: inline-block;
margin-bottom: 20px;
box-shadow: 0 4px 12px var(--shadow-color);
}
.download-button:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px var(--accent-hover);
}
.download-button:active {
transform: translateY(0);
}
.instructions {
background: var(--bg-secondary);
border-radius: 4px;
padding: 20px;
margin-top: 20px;
text-align: left;
border: 1px solid var(--border-color);
transition: background-color 0.3s ease, border-color 0.3s ease;
}
.instructions h3 {
color: var(--text-primary);
font-size: 16px;
margin-bottom: 10px;
transition: color 0.3s ease;
}
.instructions ol {
color: var(--text-secondary);
font-size: 14px;
line-height: 1.6;
padding-left: 20px;
transition: color 0.3s ease;
}
.instructions li {
margin-bottom: 8px;
}
.adhoc-info {
text-align: left;
margin-top: 20px;
padding: 1em 2em;
border-left: 3px solid var(--accent-primary);
background: var(--bg-primary);
border-radius: 4px;
transition: background-color 0.3s ease;
}
.adhoc-info-title {
font-weight: 600;
margin-bottom: 10px;
color: var(--text-primary);
transition: color 0.3s ease;
}
.adhoc-info-text {
color: var(--text-primary);
margin: 0;
transition: color 0.3s ease;
}
.footer {
text-align: center;
margin-top: 40px;
font-size: 12px;
color: var(--text-secondary);
transition: color 0.3s ease;
}
.link {
color: var(--accent-primary);
text-decoration: none;
transition: color 0.3s ease;
}
.link:hover {
text-decoration: underline;
}
.toast {
padding: 1em 3em;
font-size: 14px;
border: 1px solid var(--accent-primary);
color: var(--text-primary);
position: fixed;
bottom: 1em;
left: 50%;
transform: translateX(-50%);
max-width: 500px;
width: calc(100% - 2em);
text-align: left;
border-radius: 4px;
background-color: var(--bg-primary);
display: none;
box-shadow: 0 8px 24px var(--shadow-color);
transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}
.toast-visible {
display: block;
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateX(-50%) translateY(20px);
}
to {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
}
.toast-icon {
font-size: 1em;
position: absolute;
left: 1em;
top: 50%;
transform: translateY(-50%);
}
.toast-close {
font-size: 1em;
padding: 0.5em;
cursor: pointer;
position: absolute;
right: 1em;
top: 50%;
transform: translateY(-50%);
color: var(--text-secondary);
transition: color 0.3s ease;
}
.toast-close:hover {
color: var(--text-primary);
}
/* Smooth transitions for all elements */
* {
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}
`;
// Shared footer HTML
const sharedFooter = `
<div class="footer">
<p>
Generated with <a class="link" href="https://rockjs.dev">Rock</a> by
<a class="link" href="https://callstack.com">Callstack</a>
</p>
</div>
`;
// Shared toast functions for both iOS and Android templates
const sharedToastFunctions = () => `
function showToast() {
setTimeout(() => {
const toast = document.getElementById('home-screen-toast');
toast.classList.add('toast-visible');
}, 2000);
}
function hideToast() {
const toast = document.getElementById('home-screen-toast');
toast.classList.remove('toast-visible');
}
`;
// Base template function for creating ad-hoc distribution pages
function createAdHocTemplate({ platform, appName, version, identifier, icon, buttonText, toastMessage, script, instructions, adhocDescription, }) {
return `
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Download ${appName} for ${platform}</title>
<style>${sharedStyles}</style>
</head>
<body>
<div class="container">
<div class="app-icon">${icon}</div>
<div id="home-screen-toast" class="toast">
<span class="toast-icon">💡</span>
<p>${toastMessage}</p>
<span class="toast-close" onclick="hideToast()">✕</span>
</div>
<h1>${appName}</h1>
<p class="version">${identifier} (${version})</p>
<p class="subtitle">
Download and install the latest version of our ${platform} app directly to your
device.
</p>
<a href="#" id="action-button" class="download-button" onclick="showToast()">
${buttonText}
</a>
<script>${script}</script>
<div class="instructions">
<h3>Installation Instructions:</h3>
<ol>${instructions}</ol>
</div>
<div class="adhoc-info">
<p class="adhoc-info-title">Ad-hoc Distribution</p>
<p class="adhoc-info-text">
${adhocDescription}
<br><br>
Learn more at <a class="link" href="https://www.rockjs.dev/docs/cli/introduction#ad-hoc-distribution">Rock Ad-hoc documentation</a>.
</p>
</div>
${sharedFooter}
</div>
</body>
</html>
`;
}
export function templateIndexHtmlIOS({ appName, version, bundleIdentifier, }) {
return createAdHocTemplate({
platform: 'iOS',
appName,
version,
identifier: bundleIdentifier,
icon: '📱',
buttonText: 'Install App',
toastMessage: 'Check Home Screen to see installation progress',
script: `
// Update the link dynamically to point to the manifest.plist
const link = document.getElementById('action-button');
const currentUrl = window.location.href;
const manifestUrl = currentUrl.replace('index.html', 'manifest.plist');
link.href = \`itms-services://?action=download-manifest&url=\${encodeURIComponent(manifestUrl)}\`;
${sharedToastFunctions()}
`,
instructions: `
<li>Tap the "Install App" button above</li>
<li>When prompted, tap "Install" in the popup dialog</li>
<li>The app will now start installing and will be available on your home screen</li>
`,
adhocDescription: "This app is distributed via ad-hoc distribution for testing purposes. Your device must either be enrolled in enterprise distribution or have its UDID added to the app's provisioning profile.",
});
}
export function templateManifestPlist({ baseUrl, ipaName, bundleIdentifier, version, appName, platformIdentifier, }) {
return `
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>${baseUrl}/${ipaName}</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>${bundleIdentifier}</string>
<key>bundle-version</key>
<string>${version}</string>
<key>kind</key>
<string>software</string>
<key>platform-identifier</key>
<string>${platformIdentifier ?? 'com.apple.platform.iphoneos'}</string>
<key>title</key>
<string>${appName}</string>
</dict>
</dict>
</array>
</dict>
</plist>`;
}
export function templateIndexHtmlAndroid({ appName, version, packageName, }) {
return createAdHocTemplate({
platform: 'Android',
appName,
version,
identifier: packageName,
icon: '🤖',
buttonText: 'Download APK',
toastMessage: 'APK download started. Check your notifications to install.',
script: `
// Update the link dynamically to point to the APK file
const link = document.getElementById('action-button');
const currentUrl = window.location.href;
const apkFileName = '${appName}.apk';
link.href = currentUrl.replace('index.html', apkFileName);
${sharedToastFunctions()}
`,
instructions: `
<li>Tap the "Download APK" button above</li>
<li>Once downloaded, open the APK file from your notifications or downloads folder</li>
<li>If prompted, enable "Install from Unknown Sources" in your device settings</li>
<li>Follow the on-screen prompts to complete the installation</li>
`,
adhocDescription: 'This app is distributed via ad-hoc distribution for testing purposes. You may need to enable installation from unknown sources in your Android device settings.',
});
}
//# sourceMappingURL=adHocTemplates.js.map