piflash / index.html
S-Dreamer's picture
add light/dark toggle and ensure that the design is mobile first and fully responsiver - Follow Up Deployment
75db287 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PiFlash - Raspberry Pi Image Flasher</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="styles.css">
</head>
<body class="bg-gray-50 dark:bg-gray-900 min-h-screen transition-colors duration-200">
<div class="container mx-auto px-4 py-8 text-gray-800 dark:text-gray-200">
<!-- Header -->
<header class="mb-10 text-center">
<div class="flex justify-between items-center mb-4">
<div class="flex items-center">
<i class="fas fa-raspberry-pi text-4xl text-red-600 mr-3"></i>
<h1 class="text-4xl font-bold text-gray-800 dark:text-gray-100">PiFlash</h1>
</div>
<button id="themeToggle" class="p-2 rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200">
<i class="fas fa-moon dark:hidden"></i>
<i class="fas fa-sun hidden dark:block"></i>
</button>
</div>
<p class="text-lg text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
A simple web-based tool to flash Raspberry Pi OS images to your SD cards. No additional software required!
</p>
</header>
<!-- Main Content -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Left Column - Device Selection -->
<div class="lg:col-span-1 space-y-6">
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-md p-6 card-hover transition-colors duration-200">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-sd-card mr-2 text-blue-500"></i> Select Storage Device
</h2>
<div id="deviceList" class="space-y-3">
<!-- Devices will be populated by JavaScript -->
</div>
<button id="refreshDevices" class="w-full mt-2 flex items-center justify-center text-blue-500 hover:text-blue-700">
<i class="fas fa-sync-alt mr-2"></i> Refresh Devices
</button>
</div>
<div class="bg-white rounded-xl shadow-md p-6 card-hover">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-cog mr-2 text-purple-500"></i> Flash Options
</h2>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Validation</label>
<select id="validationOption" class="w-full p-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
<option value="verify">Verify after writing</option>
<option value="skip">Skip verification</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Compression</label>
<select id="compressionOption" class="w-full p-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
<option value="auto">Auto (recommended)</option>
<option value="always">Always decompress</option>
<option value="never">Never decompress</option>
</select>
</div>
<div class="flex items-center">
<input type="checkbox" id="unmount" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked>
<label for="unmount" class="ml-2 block text-sm text-gray-700">Unmount before writing</label>
</div>
<div class="flex items-center">
<input type="checkbox" id="eject" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked>
<label for="eject" class="ml-2 block text-sm text-gray-700">Eject when complete</label>
</div>
</div>
</div>
</div>
<!-- Middle Column - OS Selection -->
<div class="lg:col-span-1 space-y-6">
<div class="bg-white rounded-xl shadow-md p-6 card-hover h-full">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-download mr-2 text-green-500"></i> Select OS Image
</h2>
<div class="mb-4">
<div class="flex space-x-2 mb-3">
<button id="tabRecommended" class="tab-button px-3 py-1 bg-blue-100 text-blue-700 rounded-full text-sm font-medium">Recommended</button>
<button id="tabAll" class="tab-button px-3 py-1 bg-gray-100 text-gray-700 rounded-full text-sm font-medium">All</button>
<button id="tabOther" class="tab-button px-3 py-1 bg-gray-100 text-gray-700 rounded-full text-sm font-medium">Other</button>
</div>
<div class="relative">
<input type="text" id="searchOS" placeholder="Search OS images..." class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100">
<i class="fas fa-search absolute left-3 top-3 text-gray-400"></i>
</div>
</div>
<div id="osImageList" class="space-y-3 overflow-y-auto max-h-96">
<!-- OS images will be populated by JavaScript -->
</div>
<!-- Custom Image Upload -->
<div class="mt-4">
<input type="file" id="customImageFile" accept=".img,.zip,.gz,.xz" class="hidden">
<div id="customImageUpload" class="border-2 border-dashed border-gray-300 rounded-lg p-4 text-center hover:border-blue-400 cursor-pointer">
<i class="fas fa-file-upload text-3xl text-gray-400 mb-2"></i>
<h3 class="font-medium text-gray-700">Use Custom Image</h3>
<p class="text-sm text-gray-500">Upload your own .img or .zip file</p>
</div>
</div>
</div>
</div>
<!-- Right Column - Flash Progress -->
<div class="lg:col-span-1 space-y-6">
<div class="bg-white rounded-xl shadow-md p-6 card-hover">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-bolt mr-2 text-yellow-500"></i> Flash Summary
</h2>
<div id="flashSummary" class="bg-gray-50 dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg p-4 mb-4">
<div class="flex items-center mb-2">
<i class="fas fa-info-circle text-gray-500 mr-2"></i>
<h3 class="font-medium text-gray-700">Select Image and Device</h3>
</div>
<p class="text-sm text-gray-600">
Choose an OS image and storage device to get started.
</p>
</div>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Wi-Fi Configuration (Optional)</label>
<input type="text" id="wifiSSID" placeholder="SSID" class="w-full p-2 border border-gray-300 rounded-md mb-2 focus:ring-blue-500 focus:border-blue-500">
<input type="password" id="wifiPassword" placeholder="Password" class="w-full p-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Hostname (Optional)</label>
<input type="text" id="hostname" placeholder="raspberrypi" class="w-full p-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Enable SSH</label>
<select id="sshOption" class="w-full p-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
<option value="disabled">Disabled</option>
<option value="password">Enabled with password authentication</option>
<option value="key">Enabled with public key only</option>
</select>
</div>
</div>
<button id="flashButton" class="w-full mt-6 py-3 px-4 bg-gray-400 text-white font-semibold rounded-lg shadow-md transition duration-300 flex items-center justify-center cursor-not-allowed" disabled>
<i class="fas fa-bolt mr-2"></i> Select Image and Device
</button>
</div>
<!-- Progress Section (Initially Hidden) -->
<div id="progressSection" class="bg-white rounded-xl shadow-md p-6 card-hover hidden">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-spinner fa-spin mr-2 text-blue-500"></i> Flashing in Progress
</h2>
<div class="space-y-4">
<div>
<div class="flex justify-between text-sm text-gray-600 mb-1">
<span id="progressStatus">Preparing...</span>
<span id="progressPercent">0%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="progressBar" class="progress-bar bg-blue-600 h-2.5 rounded-full" style="width: 0%"></div>
</div>
</div>
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-3">
<div class="flex items-center">
<i class="fas fa-exclamation-triangle text-yellow-500 mr-2"></i>
<h3 class="font-medium text-yellow-800">Important</h3>
</div>
<p class="text-sm text-yellow-700 mt-1">
Do not remove the SD card or close this browser tab during the flashing process.
</p>
</div>
<div id="progressSteps" class="space-y-2 text-sm">
<!-- Progress steps will be populated by JavaScript -->
</div>
<div class="pt-4 border-t border-gray-200">
<p class="text-sm text-gray-500">
<i class="fas fa-clock mr-1"></i> Estimated time remaining: <span id="timeRemaining">Calculating...</span>
</p>
</div>
<button id="cancelFlash" class="w-full py-2 px-4 bg-red-600 hover:bg-red-700 text-white font-semibold rounded-lg">
Cancel Flashing
</button>
</div>
</div>
<!-- Completion Section (Initially Hidden) -->
<div id="completionSection" class="bg-white rounded-xl shadow-md p-6 card-hover hidden">
<div class="text-center">
<div class="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-green-100 mb-4">
<i class="fas fa-check text-green-600 text-xl"></i>
</div>
<h3 class="text-lg font-medium text-gray-900 mb-2">Flash Complete!</h3>
<p class="text-sm text-gray-500 mb-4" id="completionMessage">
Your SD card is ready to use.
</p>
<div class="bg-gray-50 p-3 rounded-lg text-left mb-4">
<p class="text-sm font-medium text-gray-700 mb-1">Next Steps:</p>
<ul class="text-sm text-gray-600 list-disc list-inside space-y-1">
<li>Insert the SD card into your Raspberry Pi</li>
<li>Connect power to boot the device</li>
<li>Follow the setup instructions</li>
</ul>
</div>
<button id="flashAnother" class="w-full py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none">
Flash Another Card
</button>
</div>
</div>
</div>
</div>
<!-- Footer -->
<footer class="mt-16 text-center text-sm text-gray-500">
<p>PiFlash is an open-source tool. Use at your own risk.</p>
<p class="mt-1">Not affiliated with the Raspberry Pi Foundation.</p>
<div class="flex justify-center space-x-4 mt-3">
<a href="https://github.com/your-org/piflash" class="text-blue-500 hover:text-blue-700"><i class="fab fa-github"></i> GitHub</a>
<a href="#" class="text-blue-500 hover:text-blue-700"><i class="fas fa-question-circle"></i> Help</a>
<a href="#" class="text-blue-500 hover:text-blue-700"><i class="fas fa-bug"></i> Report Issue</a>
</div>
</footer>
</div>
<script src="js/app.js"></script>
<script>
// Theme toggle functionality
const themeToggle = document.getElementById('themeToggle');
const html = document.documentElement;
// Check for saved theme preference or use system preference
const savedTheme = localStorage.getItem('theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
html.classList.toggle('dark', savedTheme === 'dark');
themeToggle.addEventListener('click', () => {
html.classList.toggle('dark');
localStorage.setItem('theme', html.classList.contains('dark') ? 'dark' : 'light');
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=S-Dreamer/piflash" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>